diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index 02bfc3d065ca..e8423a5704ce 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -5,7 +5,17 @@ NOTE: Please grant permission for repository maintainers to edit your PR. It is CODE STYLE: please follow below guide. JSON: https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/doc/JSON_STYLE.md -C++: https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/doc/CODE_STYLE.md +C++ and Markdown: https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/doc/CODE_STYLE.md + +!!!!!!!!!! WARNING !!!!!!!!!! + +If you forget to format the PR, autofix.ci app will run automated format commit for you. +When this happens, YOU MUST DO EITHER OF THE FOLLOWING: + +- Run `git pull` to merge the automated commit into your PR branch. +- Format your code locally, and force push to your PR branch. + +If you don't do this, your following work will be based on the old commit, and cause MERGE CONFLICT. --> #### Summary diff --git a/.github/workflows/autofix.yml b/.github/workflows/autofix.yml new file mode 100644 index 000000000000..5446dbae4a90 --- /dev/null +++ b/.github/workflows/autofix.yml @@ -0,0 +1,37 @@ +name: autofix.ci # needed to securely identify the workflow + +on: + pull_request: + paths: ["**.json", "**.cpp", "**.hpp", "**.h", "**.c"] + +permissions: + contents: read + +jobs: + autofix: + runs-on: ubuntu-22.04 + permissions: + contents: write + + steps: + - uses: actions/checkout@v3 + + - run: sudo apt-get install astyle + + - uses: denoland/setup-deno@v1 + with: + deno-version: v1.x + + - name: format C++ files + run: make astyle + + - name: format markdown files + run: deno fmt + + - name: json formatting + run: make style-all-json-parallel RELEASE=1 + + - uses: autofix-ci/action@8caa572fd27b0019a65e4c695447089c8d3138b9 + if: ${{ always() }} + with: + commit-message: "style(autofix.ci): automated formatting" diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml deleted file mode 100644 index 95cdfb373bcb..000000000000 --- a/.github/workflows/lint.yml +++ /dev/null @@ -1,29 +0,0 @@ -name: Code Style Check - -on: - pull_request_target: - paths: ["**.json", "**.cpp", "**.hpp", "**.h", "**.c"] - pull_request: - paths: ["**.json", "**.cpp", "**.hpp", "**.h", "**.c"] - -concurrency: - group: ${{ github.workflow }}-${{ github.event.pull_request.number }}-${{ github.event_name }} - cancel-in-progress: true - -jobs: - lint: - if: ${{ github.event_name == 'pull_request_target' }} - runs-on: ubuntu-22.04 - steps: - - uses: actions/checkout@v3 - with: - ref: ${{ github.event.pull_request.head.sha }} - - - run: sudo apt-get install astyle - - run: make astyle - - run: make style-all-json-parallel RELEASE=1 - - - uses: reviewdog/action-suggester@v1 - if: ${{ always() }} - with: - tool_name: astyle, style-json diff --git a/.github/workflows/matrix.yml b/.github/workflows/matrix.yml index d881eb0b40ae..3e2f8d71acb8 100644 --- a/.github/workflows/matrix.yml +++ b/.github/workflows/matrix.yml @@ -31,7 +31,9 @@ jobs: cmake: 0 tiles: 0 sound: 0 + lua: 0 test-stage: 1 + libbacktrace: 1 title: GCC 12, Ubuntu, Curses native: linux64 - compiler: g++-12 @@ -39,14 +41,26 @@ jobs: cmake: 1 tiles: 1 sound: 1 + lua: 1 languages: all native: linux64 - title: GCC 12, Ubuntu, Tiles, CMake, Languages + title: GCC 12, Ubuntu, Tiles, Sound, Lua, CMake, Languages + - compiler: g++-12 + os: ubuntu-22.04 + cmake: 0 + tiles: 1 + sound: 1 + lua: 1 + test-stage: 1 + libbacktrace: 1 + title: GCC 12, Ubuntu, Tiles, Sound, Lua + native: linux64 - compiler: g++-12 os: ubuntu-22.04 cmake: 0 tiles: 1 sound: 0 + lua: 0 sanitize: address native: linux64 title: GCC 12, Ubuntu, Tiles, NoSound, ASan @@ -55,6 +69,7 @@ jobs: cmake: 0 tiles: 1 sound: 0 + lua: 0 sanitize: address,undefined native: linux64 title: Clang 14, Ubuntu, Tiles, NoSound, ASan, UBSan @@ -63,10 +78,11 @@ jobs: cmake: 0 tiles: 1 sound: 1 + lua: 1 test-stage: 1 native: osx grep_clang_version_rxp: "14\\.[0-9]+\\.[0-9]+" - title: Clang 14, macOS 12, Tiles, Localize + title: Clang 14, macOS 12, Tiles, Sound, Localize, Lua name: ${{ matrix.title }} runs-on: ${{ matrix.os }} env: @@ -76,10 +92,12 @@ jobs: OS: ${{ matrix.os }} TILES: ${{ matrix.tiles }} SOUND: ${{ matrix.sound }} + LUA: ${{ matrix.lua }} SANITIZE: ${{ matrix.sanitize }} TEST_STAGE: ${{ matrix.test-stage }} LANGUAGES: ${{ matrix.languages }} EXTRA_TEST_OPTS: + LIBBACKTRACE: ${{ matrix.libbacktrace }} NATIVE: ${{ matrix.native }} RELEASE: 1 SKIP: ${{ needs.skip-duplicates.outputs.should_skip == 'true' }} diff --git a/.github/workflows/push-translation-template.yml b/.github/workflows/push-translation-template.yml index 133f3a4fe714..836df157a0d3 100644 --- a/.github/workflows/push-translation-template.yml +++ b/.github/workflows/push-translation-template.yml @@ -25,7 +25,7 @@ jobs: - name: "Install Python3" run: | sudo apt install python3-pip - sudo pip3 install polib + sudo pip3 install polib luaparser - name: "Checkout" uses: actions/checkout@v3 - name: "Generate translation template" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c3103c45efc0..3ad76c2114be 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -224,14 +224,14 @@ jobs: - name: Build CBN (linux) if: runner.os == 'Linux' && matrix.mxe == 'none' && matrix.android == 'none' run: | - make -j$((`nproc`+0)) TILES=${{ matrix.tiles }} SOUND=${{ matrix.tiles }} RELEASE=1 LANGUAGES=all PCH=0 bindist + make -j$((`nproc`+0)) TILES=${{ matrix.tiles }} SOUND=${{ matrix.tiles }} LUA=1 RELEASE=1 LANGUAGES=all PCH=0 bindist mv cataclysmbn-unstable.tar.gz cbn-${{ matrix.artifact }}-${{ needs.release.outputs.timestamp }}.tar.gz - name: Build CBN (windows) if: matrix.mxe != 'none' env: PLATFORM: /opt/mxe/usr/bin/${{ matrix.mxe }}-w64-mingw32.static.gcc11- run: | - make -j$((`nproc`+0)) CROSS="${PLATFORM}" TILES=1 SOUND=1 RELEASE=1 LANGUAGES=all PCH=0 bindist + make -j$((`nproc`+0)) CROSS="${PLATFORM}" TILES=1 SOUND=1 LUA=1 RELEASE=1 LANGUAGES=all PCH=0 bindist mv cataclysmbn-unstable.zip cbn-${{ matrix.artifact }}-${{ needs.release.outputs.timestamp }}.zip - name: Build CBN (windows msvc) if: runner.os == 'Windows' @@ -244,7 +244,7 @@ jobs: - name: Build CBN (osx) if: runner.os == 'macOS' run: | - make -j3 TILES=${{ matrix.tiles }} SOUND=${{ matrix.tiles }} RELEASE=1 LANGUAGES=all USE_HOME_DIR=1 OSX_MIN=11 PCH=0 dmgdist COMPILER=clang++ + make -j3 TILES=${{ matrix.tiles }} SOUND=${{ matrix.tiles }} LUA=1 RELEASE=1 LANGUAGES=all USE_HOME_DIR=1 OSX_MIN=11 PCH=0 dmgdist COMPILER=clang++ mv CataclysmBN-unstable.dmg cbn-${{ matrix.artifact }}-${{ needs.release.outputs.timestamp }}.dmg - name: Set up JDK 8 (android) if: runner.os == 'Linux' && matrix.android != 'none' && matrix.mxe == 'none' diff --git a/CMakeLists.txt b/CMakeLists.txt index dfc1533d737c..295b46baf743 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -16,6 +16,7 @@ SET(CMAKE_TLS_VERIFY ON) option(TILES "Build graphical tileset version." "OFF") option(CURSES "Build curses version." "ON") option(SOUND "Support for in-game sounds & music." "OFF") +option(LUA "Support for in-game scripting with Lua." "OFF") option(BACKTRACE "Support for printing stack backtraces on crash" "ON") option(LIBBACKTRACE "Print backtrace with libbacktrace." "OFF") option(USE_HOME_DIR "Use user's home directory for save files." "ON") @@ -30,6 +31,7 @@ set(CATA_CLANG_TIDY_INCLUDE_DIR "" CACHE STRING "Path to internal clang-tidy hea set(CATA_CHECK_CLANG_TIDY "" CACHE STRING "Path to check_clang_tidy.py for plugin tests") set(GIT_BINARY "" CACHE STRING "Git binary name or path.") set(PREFIX "" CACHE STRING "Location of Data & GFX directories") +set(LINKER "" CACHE STRING "Custom Linker to use") include(CTest) @@ -51,6 +53,10 @@ MESSAGE(STATUS "${PROJECT} build environment -- \n") MESSAGE(STATUS "Build realm is : ${CMAKE_SYSTEM_NAME} ${CMAKE_HOST_SYSTEM_PROCESSOR}") +IF(LINKER) + add_link_options("-fuse-ld=${LINKER}") +ENDIF() + IF(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE Debug) ENDIF(NOT CMAKE_BUILD_TYPE) @@ -61,7 +67,7 @@ if (NOT ${GIT_VERSION} MATCHES GIT-NOTFOUND) string(REPLACE "-NOTFOUND" "" GIT_VERSION ${GIT_VERSION}) FILE(WRITE ${CMAKE_SOURCE_DIR}/src/version.h "// NOLINT(cata-header-guard)\n\#define VERSION \"${GIT_VERSION}\"\n") - MESSAGE(STATUS "${PROJECT_NAME} build version is : ${GIT_VERSION}\n") + MESSAGE(STATUS "${PROJECT_NAME} build version is : ${GIT_VERSION}\n") ADD_DEFINITIONS(-DGIT_VERSION) ELSE (NOT ${GIT_VERSION} MATCHES GIT-NOTFOUND) MESSAGE("") @@ -195,21 +201,27 @@ ELSE (CMAKE_BUILD_TYPE STREQUAL Debug) ADD_DEFINITIONS(-DDATA_DIR_PREFIX) ENDIF (PREFIX AND NOT WIN32) ENDIF (CMAKE_BUILD_TYPE STREQUAL Debug) - MESSAGE(STATUS "GIT_BINARY : ${GIT_EXECUTABLE}") - MESSAGE(STATUS "DYNAMIC_LINKING : ${DYNAMIC_LINKING}") - MESSAGE(STATUS "TILES : ${TILES}") - MESSAGE(STATUS "CURSES : ${CURSES}") - MESSAGE(STATUS "SOUND : ${SOUND}") - MESSAGE(STATUS "BACKTRACE : ${BACKTRACE}") - MESSAGE(STATUS "USE_HOME_DIR : ${USE_HOME_DIR}\n") +MESSAGE(STATUS "GIT_BINARY : ${GIT_EXECUTABLE}") +MESSAGE(STATUS "DYNAMIC_LINKING : ${DYNAMIC_LINKING}") - MESSAGE(STATUS "UNITY_BUILD : ${USE_UNITY_BUILD}") - MESSAGE(STATUS "PCH_HEADER : ${USE_PCH_HEADER}") +MESSAGE(STATUS "TILES : ${TILES}") +MESSAGE(STATUS "CURSES : ${CURSES}") +MESSAGE(STATUS "SOUND : ${SOUND}") +MESSAGE(STATUS "LUA : ${LUA}") +MESSAGE(STATUS "BACKTRACE : ${BACKTRACE}") +MESSAGE(STATUS "LIBBACKTRACE : ${LIBBACKTRACE}") +MESSAGE(STATUS "USE_HOME_DIR : ${USE_HOME_DIR}\n") - MESSAGE(STATUS "LANGUAGES : ${LANGUAGES}\n") +MESSAGE(STATUS "UNITY_BUILD : ${USE_UNITY_BUILD}") +MESSAGE(STATUS "PCH_HEADER : ${USE_PCH_HEADER}") +MESSAGE(STATUS "LANGUAGES : ${LANGUAGES}\n") + +IF(LINKER) + MESSAGE(STATUS "LINKER : ${LINKER}\n") +ENDIF() - MESSAGE(STATUS "See INSTALL file for details and more info --\n") +MESSAGE(STATUS "See INSTALL file for details and more info --\n") IF(MSVC) if(CMAKE_SIZEOF_VOID_P EQUAL 8) diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md index a2a234c9910b..d13c0b815ef3 100644 --- a/CODE_OF_CONDUCT.md +++ b/CODE_OF_CONDUCT.md @@ -1,24 +1,34 @@ ## Our Pledge -In the interest of fostering an open and welcoming environment, we as contributors and maintainers pledge to making participation in our project and our community a harassment-free experience for everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity and expression, level of experience, education, socio-economic status, nationality, personal appearance, race, religion, or sexual identity and orientation. +In the interest of fostering an open and welcoming environment, we as contributors and maintainers +pledge to making participation in our project and our community a harassment-free experience for +everyone, regardless of age, body size, disability, ethnicity, sex characteristics, gender identity +and expression, level of experience, education, socio-economic status, nationality, personal +appearance, race, religion, or sexual identity and orientation. ## Our Standards 1. Assume other participants are posting in good faith, even if you disagree with what they say. 2. Make an effort to treat other participants with respect. - 1. Do not take a harsh tone towards other participants, and especially don't make personal attacks against them. - 2. Recognize that criticism of your statements is not a personal attack on you. - 3. Avoid statements about the presumed typical desires, capabilities or actions of some demographic group. + 1. Do not take a harsh tone towards other participants, and especially don't make personal + attacks against them. + 2. Recognize that criticism of your statements is not a personal attack on you. + 3. Avoid statements about the presumed typical desires, capabilities or actions of some + demographic group. 3. Be especially kind to other contributors when saying they made a mistake. -4. Don't argue unceasingly for your preferred course of action when a decision for some other course has already been made. -5. If other participants complain about the way you express your ideas, please make an effort to cater to them. +4. Don't argue unceasingly for your preferred course of action when a decision for some other course + has already been made. +5. If other participants complain about the way you express your ideas, please make an effort to + cater to them. 6. Don't raise unrelated political issues. -7. If you feel these standards are being violated, please alert the project's "ombudsman" Jakob at lamandus@hotmail.com +7. If you feel these standards are being violated, please alert the project's "ombudsman" Jakob at + lamandus@hotmail.com ## Attribution -This Code of Conduct is adapted from the [Contributor Covenant][CoC homepage], version 1.4, available at [http://contributor-covenant.org/version/1/4][CoC version] and the [GNU Kind Communications Guidelines][GKCG homepage]. - +This Code of Conduct is adapted from the [Contributor Covenant][CoC homepage], version 1.4, +available at [http://contributor-covenant.org/version/1/4][CoC version] and the +[GNU Kind Communications Guidelines][GKCG homepage]. [CoC homepage]: http://contributor-covenant.org [CoC version]: http://contributor-covenant.org/version/1/4/ diff --git a/ISSUES.md b/ISSUES.md index dd800f72d7a6..5fa8ba6ce18f 100644 --- a/ISSUES.md +++ b/ISSUES.md @@ -2,24 +2,28 @@ ## How to create new issues properly -GitHub issues are used for everything from bug reporting to suggesting long-term ideas. You can make everything run much smoother by following some simple rules. +GitHub issues are used for everything from bug reporting to suggesting long-term ideas. You can make +everything run much smoother by following some simple rules. ### Rule zero Always give your issue a meaningful title as this is the first thing anyone will see. -Note: `[CR]` and `[WIP]` "tags" are meaningful only for PRs. All open issues by definition are request for comments and work in progress. +Note: `[CR]` and `[WIP]` "tags" are meaningful only for PRs. All open issues by definition are +request for comments and work in progress. ### Bug reports -Before you submit a bug always search the current list of issues to see if it has been reported already. +Before you submit a bug always search the current list of issues to see if it has been reported +already. Your bug report has to include: - On what OS did you experience the problem (Windows, Linux, OS X etc.) - What version were you playing: - - Tiles or Curses (text-based) - - Version string (preferably full version e.g. "0.C-4547-g3f1c109", or Jenkins build number e.g. 3245) +- Tiles or Curses (text-based) +- Version string (preferably full version e.g. "0.C-4547-g3f1c109", or Jenkins build number + e.g. 3245) - Description of the problem written in a way that enables anyone to try and recreate it Your bug report may include: @@ -32,24 +36,42 @@ Bonus points for: - Checking if the bug exists under latest experimental build - Checking if it is OS specific -The OS and BN version are very important - with the pace of changes here it is possible the bug you have encountered has already been fixed. After that reproducibility is the key, so write your report with all the necessary details. +The OS and BN version are very important - with the pace of changes here it is possible the bug you +have encountered has already been fixed. After that reproducibility is the key, so write your report +with all the necessary details. ### Enhancements and addition ideas -We have hundreds of issues open - most of them are ideas and suggestions. If you have a general idea or anything that can't be easily described in terms of *current* code changes you'd be better off suggesting it in the appropriate section of [the forum](https://discourse.cataclysmdda.org/). You'll also get much broader exposure for your idea there. After developing a polished idea on the forum, it should be easy to make a GitHub issue for it. +We have hundreds of issues open - most of them are ideas and suggestions. If you have a general idea +or anything that can't be easily described in terms of _current_ code changes you'd be better off +suggesting it in the appropriate section of [the forum](https://discourse.cataclysmdda.org/). You'll +also get much broader exposure for your idea there. After developing a polished idea on the forum, +it should be easy to make a GitHub issue for it. -Please first search if something like what you have on mind has been already proposed. If so, feel free to join the discussion! If your idea is related but sufficiently different, open a new issue and refer to the older discussion (use GitHub's `#issue_number` reference system). +Please first search if something like what you have on mind has been already proposed. If so, feel +free to join the discussion! If your idea is related but sufficiently different, open a new issue +and refer to the older discussion (use GitHub's `#issue_number` reference system). Remember to take part in the discussion of your suggestions. ### Questions -You should direct your questions to the forum or ask on IRC. You should also read the included documentation and additional text files, e.g. [COMPILING.md](doc/COMPILING/COMPILING.md) if you have problems building. +You should direct your questions to the forum or ask on IRC. You should also read the included +documentation and additional text files, e.g. [COMPILING.md](doc/COMPILING/COMPILING.md) if you have +problems building. ## Bounties -Placing a bounty *does not* necessarily mean that change will be incorporated into the main game. Please coordinate in the issue you intend to place a bounty on to determine if it is a change the project will accept, and keep in mind that placing a bounty will not confer special status on the issue. A good way of thinking about bounties is as encouragement for contributors to work on a particular issue, and certainly not as "paying for features". +Placing a bounty _does not_ necessarily mean that change will be incorporated into the main game. +Please coordinate in the issue you intend to place a bounty on to determine if it is a change the +project will accept, and keep in mind that placing a bounty will not confer special status on the +issue. A good way of thinking about bounties is as encouragement for contributors to work on a +particular issue, and certainly not as "paying for features". ## Issue resolution -We do not assign people to issues. If you plan to work on a bug fix or a validated idea feel free to just comment about that. Actual PRs are of much greater value than any assignments. In general the first correct PR about something will be the PR that will get merged, but remember: we are using Git - you can collaborate with someone else easily by sending them patches or PRs against their PR branch. +We do not assign people to issues. If you plan to work on a bug fix or a validated idea feel free to +just comment about that. Actual PRs are of much greater value than any assignments. In general the +first correct PR about something will be the PR that will get merged, but remember: we are using +Git - you can collaborate with someone else easily by sending them patches or PRs against their PR +branch. diff --git a/LICENSE.txt b/LICENSE.txt index 105a4e34cc71..f28164a3970d 100644 --- a/LICENSE.txt +++ b/LICENSE.txt @@ -10,6 +10,10 @@ PLF List and PLF Colony (src/list.h, src/colony.h) are licensed under the zLib l getpost (tools/json_tools/format/getpost.h) is licensed under the MIT license, see file for text of license. +Lua (src/lua/*) is licensed under the MIT license, see src_lua/LICENSE.md for text of license. + +sol2 (src/sol/*) is licensed under the MIT license, see src/sol/sol.hpp for text of license. + fmtlib (src/fmtlib_*) is licensed under the MIT license (https://github.com/fmtlib/fmt/blob/master/LICENSE.rst). The full license text is as follows: diff --git a/Makefile b/Makefile index 958d9dac6028..d4ebcb583b60 100644 --- a/Makefile +++ b/Makefile @@ -11,6 +11,7 @@ # LTO Set to 1 to enable link-time optimization. # TILES Set to 1 to enable tiles. Requires SDL. # SOUND Set to 1 to enable sounds. Requires SDL. +# LUA Set to 1 to enable Lua. # # Platforms: # Linux/Cygwin native @@ -52,7 +53,7 @@ # make TILES=1 SOUND=1 # Disable backtrace support, not available on all platforms # make BACKTRACE=0 -# Use libbacktrace. Only has effect if BACKTRACE=1. (currently only for MinGW builds) +# Use libbacktrace. Only has effect if BACKTRACE=1. (currently only for MinGW and Linux builds) # make LIBBACKTRACE=1 # Compile localization files for specified languages # make localization LANGUAGES="[ lang_id_2][ ...]" @@ -166,8 +167,11 @@ CHKJSON_BIN = $(BUILD_PREFIX)chkjson BINDIST_DIR = $(BUILD_PREFIX)bindist BUILD_DIR = $(CURDIR) SRC_DIR = src +LUA_SRC_DIR = $(SRC_DIR)/lua ASTYLE_BINARY = astyle +CXXFLAGS += -I$(SRC_DIR) -I$(LUA_SRC_DIR) + # Enable astyle by default ifndef ASTYLE ASTYLE = 1 @@ -264,8 +268,10 @@ endif # when preprocessor defines change, but the source doesn't ODIR = $(BUILD_PREFIX)obj ODIRTILES = $(BUILD_PREFIX)obj/tiles +ODIRLUA = $(BUILD_PREFIX)obj/lua W32ODIR = $(BUILD_PREFIX)objwin W32ODIRTILES = $(W32ODIR)/tiles +W32ODIRLUA = $(W32ODIR)/lua ifdef AUTO_BUILD_PREFIX BUILD_PREFIX = $(if $(RELEASE),release-)$(if $(DEBUG_SYMBOLS),symbol-)$(if $(TILES),tiles-)$(if $(SOUND),sound-)$(if $(BACKTRACE),back-$(if $(LIBBACKTRACE),libbacktrace-))$(if $(SANITIZE),sanitize-)$(if $(MAPSIZE),map-$(MAPSIZE)-)$(if $(USE_XDG_DIR),xdg-)$(if $(USE_HOME_DIR),home-)$(if $(DYNAMIC_LINKING),dynamic-)$(if $(MSYS2),msys2-) @@ -393,7 +399,11 @@ ifeq ($(RELEASE), 1) OTHERS += $(RELEASE_FLAGS) DEBUG = ifndef DEBUG_SYMBOLS - DEBUGSYMS = + ifeq ($(LIBBACKTRACE), 1) + DEBUGSYMS = -g1 + else + DEBUGSYMS = + endif endif DEFINES += -DRELEASE # Check for astyle or JSON regressions on release builds. @@ -573,6 +583,7 @@ ifeq ($(TARGETSYSTEM),WINDOWS) BINDIST = $(W32BINDIST) BINDIST_CMD = $(W32BINDIST_CMD) ODIR = $(W32ODIR) + ODIRLUA = $(W32ODIRLUA) ifeq ($(DYNAMIC_LINKING), 1) # Windows isn't sold with programming support, these are static to remove MinGW dependency. LDFLAGS += -static-libgcc -static-libstdc++ @@ -756,9 +767,6 @@ ifeq ($(TARGETSYSTEM),WINDOWS) LDFLAGS += -lgdi32 -lwinmm -limm32 -lole32 -loleaut32 -lversion ifeq ($(BACKTRACE),1) LDFLAGS += -ldbghelp - ifeq ($(LIBBACKTRACE),1) - LDFLAGS += -lbacktrace - endif endif endif @@ -766,6 +774,7 @@ ifeq ($(BACKTRACE),1) DEFINES += -DBACKTRACE ifeq ($(LIBBACKTRACE),1) DEFINES += -DLIBBACKTRACE + LDFLAGS += -lbacktrace endif endif @@ -794,6 +803,7 @@ TESTSRC := $(wildcard tests/*.cpp) TESTHDR := $(wildcard tests/*.h) JSON_FORMATTER_SOURCES := tools/format/format.cpp src/json.cpp CHKJSON_SOURCES := src/chkjson/chkjson.cpp src/json.cpp +LUA_SOURCES := $(wildcard $(LUA_SRC_DIR)/*.c) CLANG_TIDY_PLUGIN_SOURCES := \ $(wildcard tools/clang-tidy-plugin/*.cpp tools/clang-tidy-plugin/*/*.cpp) TOOLHDR := $(wildcard tools/*/*.h) @@ -815,6 +825,13 @@ ifeq ($(TARGETSYSTEM),WINDOWS) endif OBJS = $(sort $(patsubst %,$(ODIR)/%,$(_OBJS))) +ifeq ($(LUA), 1) + DEFINES += -DLUA + LUA_OBJS = $(sort $(LUA_SOURCES:$(LUA_SRC_DIR)/%.c=$(ODIRLUA)/%.o)) +else + LUA_OBJS = +endif + ifdef LANGUAGES L10N = localization endif @@ -872,12 +889,12 @@ endif all: version $(CHECKS) $(TARGET) $(L10N) $(TESTS) @ -$(TARGET): $(OBJS) +$(TARGET): $(OBJS) $(LUA_OBJS) ifeq ($(VERBOSE),1) - +$(LD) $(W32FLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) + +$(LD) $(W32FLAGS) -o $(TARGET) $(OBJS) $(LUA_OBJS) $(LDFLAGS) else @echo "Linking $@..." - @+$(LD) $(W32FLAGS) -o $(TARGET) $(OBJS) $(LDFLAGS) + @+$(LD) $(W32FLAGS) -o $(TARGET) $(OBJS) $(LUA_OBJS) $(LDFLAGS) @echo Done! endif @@ -892,12 +909,12 @@ endif $(PCH_P): $(PCH_H) -$(CXX) $(CPPFLAGS) $(DEFINES) $(subst -Werror,,$(CXXFLAGS)) -c $(PCH_H) -o $(PCH_P) -$(BUILD_PREFIX)$(TARGET_NAME).a: $(OBJS) +$(BUILD_PREFIX)$(TARGET_NAME).a: $(OBJS) $(LUA_OBJS) ifeq ($(VERBOSE),1) - $(AR) rcs $(BUILD_PREFIX)$(TARGET_NAME).a $(filter-out $(ODIR)/main.o $(ODIR)/messages.o,$(OBJS)) + $(AR) rcs $(BUILD_PREFIX)$(TARGET_NAME).a $(filter-out $(ODIR)/main.o $(ODIR)/messages.o,$(OBJS)) $(LUA_OBJS) else @echo "Creating $@..." - @$(AR) rcs $(BUILD_PREFIX)$(TARGET_NAME).a $(filter-out $(ODIR)/main.o $(ODIR)/messages.o,$(OBJS)) + @$(AR) rcs $(BUILD_PREFIX)$(TARGET_NAME).a $(filter-out $(ODIR)/main.o $(ODIR)/messages.o,$(OBJS)) $(LUA_OBJS) endif .PHONY: version @@ -911,6 +928,7 @@ version: # Unconditionally create the object dir on every invocation. $(shell mkdir -p $(ODIR)) +$(shell mkdir -p $(ODIRLUA)) $(ODIR)/%.o: $(SRC_DIR)/%.cpp $(PCH_P) ifeq ($(VERBOSE), 1) @@ -928,6 +946,14 @@ else @$(RC) $(RFLAGS) $< -o $@ endif +$(ODIRLUA)/%.o: $(LUA_SRC_DIR)/%.c +ifeq ($(VERBOSE), 1) + $(CXX) -xc -std=c11 -c $< -o $@ +else + @echo $(@F) + @$(CXX) -xc -std=c11 -c $< -o $@ +endif + src/version.h: version src/version.cpp: src/version.h diff --git a/README.ko.md b/README.ko.md index 29da2f55379b..fd39ffe1f0c4 100644 --- a/README.ko.md +++ b/README.ko.md @@ -3,8 +3,7 @@
- [![en][icon-en]][en] - [![ko][icon-ko]][ko] +[![en][icon-en]][en] [![ko][icon-ko]][ko]
@@ -13,36 +12,48 @@ [ko]: ./README.ko.md [icon-ko]: https://img.shields.io/badge/lang-ko-orange?style=flat-square - - 카타클리즘: 밝은 밤은 포스트 아포칼립스 세계에서 벌어지는 공상과학 로그라이크입니다. -"좀비 게임"이라 불리기도 하지만, 그뿐만이 아닙니다. 험난하고, 절차적으로 생성되는 세계에서 살아남아야 합니다. 이제는 죽어버린 문명의 잔해를 뒤져 음식, 장비, 운이 좋다면 연료가 가득 찬 차량을 찾아 탈출하세요. +"좀비 게임"이라 불리기도 하지만, 그뿐만이 아닙니다. 험난하고, 절차적으로 생성되는 세계에서 +살아남아야 합니다. 이제는 죽어버린 문명의 잔해를 뒤져 음식, 장비, 운이 좋다면 연료가 가득 찬 차량을 +찾아 탈출하세요. -좀비, 거대 곤충, 킬러 로봇, 더 이상하고 치명적인 것들, 그리고 당신이 가진 것을 노리는 이들까지, 강력한 괴물들과 싸우거나 도망치세요. +좀비, 거대 곤충, 킬러 로봇, 더 이상하고 치명적인 것들, 그리고 당신이 가진 것을 노리는 이들까지, +강력한 괴물들과 싸우거나 도망치세요. 카타클리즘을 멈출 방법을 찾거나.... 가장 강력한 괴물 중 하나가 되세요. -> 카타클리즘: 밝은 밤(Cataclysm: Bright Nights)은 카타클리즘: 어두운 나날(Cataclysm: Dark Days Ahead)의 포크입니다. [위키](https://github.com/cataclysmbnteam/cataclysm-BN/wiki/Changes-so-far)에서 어떤 차이가 있는지 확인하세요. +> 카타클리즘: 밝은 밤(Cataclysm: Bright Nights)은 카타클리즘: 어두운 나날(Cataclysm: Dark Days +> Ahead)의 포크입니다. +> [위키](https://github.com/cataclysmbnteam/cataclysm-BN/wiki/Changes-so-far)에서 어떤 차이가 있는지 +> 확인하세요. ## 다운로드 -[![안정판][stable-releases-badge]][stable-releases] [![최신 릴리즈][all-releases-badge]][all-releases] +### 실행 파일 + +[![Stable][stable-releases-badge]][stable-releases] [![Recent][all-releases-badge]][all-releases] -[stable-releases]: https://github.com/cataclysmbnteam/cataclysm-BN/releases/tag/cbn-0.3 -[stable-releases-badge]: https://img.shields.io/github/v/release/cataclysmbnteam/cataclysm-BN?style=for-the-badge&color=success&label=stable -[all-releases]: https://github.com/cataclysmbnteam/cataclysm-BN/releases -[all-releases-badge]: https://img.shields.io/github/v/release/cataclysmbnteam/cataclysm-BN?style=for-the-badge&color=important&label=Latest%20Release&include_prereleases&sort=date +### 소스 코드 -| [소스 코드][source-zip-archive] | [저장소에서 클론하기][clone] | -| :-----------------------------: | :--------------------------: | +[![Source Code][source-badge]][source] [![Zip Archive][clone-badge]][clone] -[source-zip-archive]: https://github.com/cataclysmbnteam/cataclysm-BN/archive/master.zip "소스 코드를 .zip 아카이브로 다운로드할 수 있습니다" -[clone]: https://github.com/cataclysmbnteam/cataclysm-BN/ "GitHub 저장소에서 클론할 수 있습니다" +[stable-releases]: https://github.com/cataclysmbnteam/Cataclysm-BN/releases/latest "안정판 실행 파일 내려받기" +[stable-releases-badge]: https://img.shields.io/github/v/release/cataclysmbnteam/Cataclysm-BN?style=for-the-badge&color=success&label=안정판 +[all-releases]: https://github.com/cataclysmbnteam/Cataclysm-BN/releases?q=prerelease%3Atrue&expanded=true "실험판 실행 파일 내려받기" +[all-releases-badge]: https://img.shields.io/github/v/release/cataclysmbnteam/Cataclysm-BN?style=for-the-badge&color=important&label=최신%20실험판&include_prereleases&sort=date +[source]: https://github.com/cataclysmbnteam/Cataclysm-BN/archive/master.zip "소스 코드를 .zip 아카이브로 다운로드할 수 있습니다" +[source-badge]: https://img.shields.io/badge/ZIP%20아카이브로%20내려받기-black?style=for-the-badge&logo=github +[clone]: https://github.com/cataclysmbnteam/Cataclysm-BN/ "GitHub 저장소에서 클론할 수 있습니다" +[clone-badge]: https://img.shields.io/badge/저장소에서%20클론하기-black?style=for-the-badge&logo=github ## 빌드하기 -[COMPILING.md](doc/COMPILING/COMPILING.md)를 참고하세요 - 리눅스, OS X, 윈도우즈와 BSD에서 빌드하기 위한 일반적인 정보부터 보다 자세한 레시피가 담겨있습니다. [COMPILER_SUPPORT.md](doc/COMPILING/COMPILER_SUPPORT.md)에서 지원하는 컴파일러를 확인할 수 있습니다. 더 자세한 정보는 [doc/](https://github.com/cataclysmbnteam/cataclysm-BN/tree/upload/doc)에서도 찾아볼 수 있습니다. +[COMPILING.md](doc/COMPILING/COMPILING.md)를 참고하세요 - 리눅스, OS X, 윈도우즈와 BSD에서 빌드하기 +위한 일반적인 정보부터 보다 자세한 레시피가 담겨있습니다. +[COMPILER_SUPPORT.md](doc/COMPILING/COMPILER_SUPPORT.md)에서 지원하는 컴파일러를 확인할 수 있습니다. +더 자세한 정보는 [doc/](https://github.com/cataclysmbnteam/cataclysm-BN/tree/upload/doc)에서도 +찾아볼 수 있습니다. 또한 다음 빌드 가이드도 있습니다. @@ -52,17 +63,20 @@ ## 기여하기 -> 카타클리즘: 밝은 밤은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 3.0 라이선스로 개발되고 있습니다. 소스 코드와 게임 내용물은 어떠한 목적으로든 사용, 수정, 재배포가 가능합니다. 자세한 내용은 를 참고하세요. -> 일부 코드는 프로젝트와 함께 배포되지만, 다른 소프트웨어 라이선스에 따라 배포됩니다. 다른 소프트웨어 라이선스에 따라 배포되는 파일들은 각 파일에 라이선스 공지가 포함되어 있습니다. +> 카타클리즘: 밝은 밤은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 3.0 라이선스로 개발되고 +> 있습니다. 소스 코드와 게임 내용물은 어떠한 목적으로든 사용, 수정, 재배포가 가능합니다. 자세한 +> 내용은 를 참고하세요. 일부 코드는 프로젝트와 함께 +> 배포되지만, 다른 소프트웨어 라이선스에 따라 배포됩니다. 다른 소프트웨어 라이선스에 따라 배포되는 +> 파일들은 각 파일에 라이선스 공지가 포함되어 있습니다. [CONTRIBUTING.ko.md](./doc/CONTRIBUTING.ko.md)에서 자세한 내용을 확인할 수 있습니다. ## 커뮤니티 -| [저장소][repo] | [토론][discussion] | [공식 저장소][discord] | [BN 채널@모딩 커뮤니티][modding] | -| :------------: | :----------------: | :--------------------: | :------------------------------: | +[![Discussions](https://img.shields.io/badge/포럼에서%20토론하기-black?style=for-the-badge&logo=github)][discussion] +[![Discord](https://img.shields.io/discord/830879262763909202?style=for-the-badge&logo=discord&label=공식%20디스코드%20서버)][discord] +[![Discussions](https://img.shields.io/badge/CDDA%20모딩%20커뮤니티-green?style=for-the-badge&logo=discord)][modding] -[repo]: https://github.com/cataclysmbnteam/cataclysm-BN [discussion]: https://github.com/cataclysmbnteam/cataclysm-BN/discussions [discord]: https://discord.gg/XW7XhXuZ89 [modding]: https://discord.gg/B5q4XCa "비공식 DDA모딩 커뮤니티에도 BN 채널이 있습니다." @@ -71,11 +85,13 @@ #### 튜토리얼이 있나요? -메인 메뉴의 **Special** 메뉴에서 찾을 수 있습니다. (코드 변경으로 인해 튜토리얼이 작동하지 않을 수 있습니다.) 게임 내에서도 `?` 키를 눌러 도움 메뉴에 접근할 수 있습니다. +메인 메뉴의 **Special** 메뉴에서 찾을 수 있습니다. (코드 변경으로 인해 튜토리얼이 작동하지 않을 수 +있습니다.) 게임 내에서도 `?` 키를 눌러 도움 메뉴에 접근할 수 있습니다. #### 단축키를 어떻게 바꾸나요? -`?` 키를 누르고 `1` 키를 눌러 전체 단축키 목록을 확인할 수 있습니다. `+` 키를 눌러 단축키를 추가할 수 있고, `a-w` 키를 눌러 해당 행동을 선택한 후, 할당할 키를 누르면 됩니다. +`?` 키를 누르고 `1` 키를 눌러 전체 단축키 목록을 확인할 수 있습니다. `+` 키를 눌러 단축키를 추가할 +수 있고, `a-w` 키를 눌러 해당 행동을 선택한 후, 할당할 키를 누르면 됩니다. #### 새 세계를 어떻게 시작하나요? @@ -83,7 +99,9 @@ #### 버그를 발견했어요. 어떻게 해야 하나요? -디버그 메뉴에서 [버그 리포트](https://github.com/cataclysmbnteam/cataclysm-BN/issues/new?template=bug_report.yml)를 제출할 수 있습니다. +디버그 메뉴에서 +[버그 리포트](https://github.com/cataclysmbnteam/cataclysm-BN/issues/new?template=bug_report.yml)를 +제출할 수 있습니다. 게임 내에서 `Submit a bug report on github`를 실행하여 이슈를 제출할 수 있습니다. @@ -97,4 +115,5 @@ #### 제안을 하고 싶어요. 어떻게 해야 하나요? -[토론 페이지](https://github.com/cataclysmbnteam/cataclysm-BN/discussions/categories/ideas)에서 아이디어를 제안할 수 있습니다. 새 기능, 포팅 요청, 모드 아이디어, 무엇이든지요! +[토론 페이지](https://github.com/cataclysmbnteam/cataclysm-BN/discussions/categories/ideas)에서 +아이디어를 제안할 수 있습니다. 새 기능, 포팅 요청, 모드 아이디어, 무엇이든지요! diff --git a/README.md b/README.md index 4e939f0f8c7e..e03b4a2754b5 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,7 @@
- [![en][icon-en]][en] - [![ko][icon-ko]][ko] +[![en][icon-en]][en] [![ko][icon-ko]][ko]
@@ -13,12 +12,16 @@ [ko]: ./README.ko.md [icon-ko]: https://img.shields.io/badge/lang-ko-orange?style=flat-square - Cataclysm: Bright Nights is a roguelike with sci-fi elements set in a post-apocalyptic world. -While some have described it as a "zombie game", there is far more to Cataclysm than that. Struggle to survive in a harsh, persistent, procedurally generated world. Scavenge the remnants of a dead civilization for food, equipment, or, if you are lucky, a vehicle with a full tank of gas to get you the hell out of there. +While some have described it as a "zombie game", there is far more to Cataclysm than that. Struggle +to survive in a harsh, persistent, procedurally generated world. Scavenge the remnants of a dead +civilization for food, equipment, or, if you are lucky, a vehicle with a full tank of gas to get you +the hell out of there. -Fight to defeat or escape from a wide variety of powerful monstrosities, from zombies to giant insects to killer robots and things far stranger and deadlier, and against the others like yourself, who want what you have. +Fight to defeat or escape from a wide variety of powerful monstrosities, from zombies to giant +insects to killer robots and things far stranger and deadlier, and against the others like yourself, +who want what you have. Find a way to stop the Cataclysm ... or become one of its strongest monsters. @@ -27,42 +30,54 @@ Find a way to stop the Cataclysm ... or become one of its strongest monsters. ## Downloads +### Executables + [![Stable][stable-releases-badge]][stable-releases] [![Recent][all-releases-badge]][all-releases] -[stable-releases]: https://github.com/cataclysmbnteam/Cataclysm-BN/releases/tag/cbn-0.3 -[stable-releases-badge]: -[all-releases]: https://github.com/cataclysmbnteam/Cataclysm-BN/releases -[all-releases-badge]: https://img.shields.io/github/v/release/cataclysmbnteam/Cataclysm-BN?style=for-the-badge&color=important&label=Latest%20Release&include_prereleases&sort=date +### Source Code -| [Source Code][source-zip-archive] | [Clone From Repo][clone] | -| :-------------------------------: | :----------------------: | +[![Source Code][source-badge]][source] [![Zip Archive][clone-badge]][clone] -[source-zip-archive]: https://github.com/cataclysmbnteam/Cataclysm-BN/archive/master.zip "The source can be downloaded as a .zip archive" +[stable-releases]: https://github.com/cataclysmbnteam/Cataclysm-BN/releases/latest "Download stable executable" +[stable-releases-badge]: https://img.shields.io/github/v/release/cataclysmbnteam/Cataclysm-BN?style=for-the-badge&color=success&label=stable "Download experimental executable" +[all-releases]: https://github.com/cataclysmbnteam/Cataclysm-BN/releases?q=prerelease%3Atrue&expanded=true +[all-releases-badge]: https://img.shields.io/github/v/release/cataclysmbnteam/Cataclysm-BN?style=for-the-badge&color=important&label=Latest%20Release&include_prereleases&sort=date +[source]: https://github.com/cataclysmbnteam/Cataclysm-BN/archive/master.zip "The source can be downloaded as a .zip archive" +[source-badge]: https://img.shields.io/badge/Zip%20Archive-black?style=for-the-badge&logo=github [clone]: https://github.com/cataclysmbnteam/Cataclysm-BN/ "clone from our GitHub repo" +[clone-badge]: https://img.shields.io/badge/Clone%20From%20Repo-black?style=for-the-badge&logo=github ## Compile -Please read [COMPILING.md](doc/COMPILING/COMPILING.md) - it covers general information and more specific recipes for Linux, OS X, Windows and BSD. See [COMPILER_SUPPORT.md](doc/COMPILING/COMPILER_SUPPORT.md) for details on which compilers we support. And you can always dig for more information in [doc/](https://github.com/cataclysmbnteam/Cataclysm-BN/tree/upload/doc). +Please read [COMPILING.md](doc/COMPILING/COMPILING.md) - it covers general information and more +specific recipes for Linux, OS X, Windows and BSD. See +[COMPILER_SUPPORT.md](doc/COMPILING/COMPILER_SUPPORT.md) for details on which compilers we support. +And you can always dig for more information in +[doc/](https://github.com/cataclysmbnteam/Cataclysm-BN/tree/upload/doc). We also have the following build guides: - Building on Windows with `MSYS2` at [COMPILING-MSYS.md](doc/COMPILING/COMPILING-MSYS.md) - Building on Windows with `vcpkg` at [COMPILING-VS-VCPKG.md](doc/COMPILING/COMPILING-VS-VCPKG.md) -- Building with `cmake` at [COMPILING-CMAKE.md](doc/COMPILING/COMPILING-CMAKE.md) (_unofficial guide_) +- Building with `cmake` at [COMPILING-CMAKE.md](doc/COMPILING/COMPILING-CMAKE.md) (_unofficial + guide_) ## Contribute -> Cataclysm: Bright Nights developed under Creative Commons Attribution ShareAlike 3.0 license. The code and content of the game is free to use, modify, and redistribute for any purpose whatsoever. See http://creativecommons.org/licenses/by-sa/3.0/ for details. -> Some code distributed with the project is not part of the project and is released under different software licenses, the files covered by different software licenses have their own license notices. +> Cataclysm: Bright Nights developed under Creative Commons Attribution ShareAlike 3.0 license. The +> code and content of the game is free to use, modify, and redistribute for any purpose whatsoever. +> See http://creativecommons.org/licenses/by-sa/3.0/ for details. Some code distributed with the +> project is not part of the project and is released under different software licenses, the files +> covered by different software licenses have their own license notices. Please see [CONTRIBUTING.md](./doc/CONTRIBUTING.md) for details. ## Community -| [Repository][repo] | [Discussions][discussion] | [Official Discord][discord] | [BN Channel@Modding Community][modding] | -| :----------------: | :-----------------------: | :-------------------------: | :-------------------------------------: | +[![Discussions](https://img.shields.io/badge/Discussions-black?style=for-the-badge&logo=github)][discussion] +[![Discord](https://img.shields.io/discord/830879262763909202?style=for-the-badge&logo=discord)][discord] +[![Discussions](https://img.shields.io/badge/CDDA%20Modding-green?style=for-the-badge&logo=discord)][modding] -[repo]: https://github.com/cataclysmbnteam/Cataclysm-BN [discussion]: https://github.com/cataclysmbnteam/Cataclysm-BN/discussions [discord]: https://discord.gg/XW7XhXuZ89 [modding]: https://discord.gg/B5q4XCa "Unofficial DDA modding community discord has a BN channel" @@ -71,11 +86,15 @@ Please see [CONTRIBUTING.md](./doc/CONTRIBUTING.md) for details. #### Is there a tutorial? -Yes, you can find the tutorial in the **Special** menu at the main menu (be aware that due to many code changes the tutorial may not function). You can also access documentation in-game via the `?` key. +Yes, you can find the tutorial in the **Special** menu at the main menu (be aware that due to many +code changes the tutorial may not function). You can also access documentation in-game via the `?` +key. #### How can I change the key bindings? -Press the `?` key, followed by the `1` key to see the full list of key commands. Press the `+` key to add a key binding, select which action with the corresponding letter key `a-w`, and then the key you wish to assign to that action. +Press the `?` key, followed by the `1` key to see the full list of key commands. Press the `+` key +to add a key binding, select which action with the corresponding letter key `a-w`, and then the key +you wish to assign to that action. #### How can I start a new world? @@ -83,7 +102,8 @@ Press the `?` key, followed by the `1` key to see the full list of key commands. #### I've found a bug. What should I do? -[Bug report](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/new?template=bug_report.yml) can be submitted via debug menu. +[Bug report](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/new?template=bug_report.yml) can +be submitted via debug menu. Run `Submit a bug report on github` inside the game to submit an issue. @@ -97,5 +117,9 @@ It will open a bug report on browser with `Version and configuration` filled in. #### I would like to make a suggestion. What should I do? -- For simple ideas: please visit [our Discussions page](https://github.com/cataclysmbnteam/Cataclysm-BN/discussions/categories/ideas). It could be a new feature, a port request, a mod idea, or anything else. -- Please submit an issue on [our GitHub page](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/) using [feature request form](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/new?template=feature_request.yml). +- For simple ideas: please visit + [our Discussions page](https://github.com/cataclysmbnteam/Cataclysm-BN/discussions/categories/ideas). + It could be a new feature, a port request, a mod idea, or anything else. +- Please submit an issue on + [our GitHub page](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/) using + [feature request form](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/new?template=feature_request.yml). diff --git a/build-scripts/build.sh b/build-scripts/build.sh index 1fa34f1e4fcc..20b89748c375 100755 --- a/build-scripts/build.sh +++ b/build-scripts/build.sh @@ -80,6 +80,7 @@ then -DCMAKE_BUILD_TYPE="$build_type" \ -DTILES=${TILES:-0} \ -DSOUND=${SOUND:-0} \ + -DLIBBACKTRACE=${LIBBACKTRACE:-0} \ "${cmake_extra_opts[@]}" \ .. if [ -n "$CATA_CLANG_TIDY" ] @@ -149,7 +150,7 @@ else else export BACKTRACE=1 fi - make -j "$num_jobs" RELEASE=1 CCACHE=1 CROSS="$CROSS_COMPILATION" LANGUAGES="all" LINTJSON=0 + make -j "$num_jobs" RELEASE=1 CCACHE=1 CROSS="$CROSS_COMPILATION" LANGUAGES="all" LINTJSON=0 LIBBACKTRACE="$LIBBACKTRACE" export UBSAN_OPTIONS=print_stacktrace=1 if [ "$OS" == "macos-12" ] @@ -176,7 +177,13 @@ else # Use a blacklist of mods that currently fail to load cleanly. Hopefully this list will # shrink over time. blacklist=build-scripts/mod_test_blacklist - mods="$(./build-scripts/get_all_mods.py $blacklist)" + if [ "$LUA" == "1" ] + then + do_lua="1" + else + do_lua="0" + fi + mods="$(./build-scripts/get_all_mods.py $blacklist $do_lua)" run_tests ./tests/cata_test --user-dir=all_modded --mods="$mods" '~*' fi fi diff --git a/build-scripts/get_all_mods.py b/build-scripts/get_all_mods.py index 59945a36b510..09278451d629 100755 --- a/build-scripts/get_all_mods.py +++ b/build-scripts/get_all_mods.py @@ -4,7 +4,10 @@ import glob import json -blacklist_filename, = sys.argv[1:] +assert(len(sys.argv) == 3) +blacklist_filename = sys.argv[1] +do_lua = sys.argv[2] == "1" + with open(blacklist_filename) as blacklist_file: blacklist = {s.rstrip('\n') for s in blacklist_file.readlines()} @@ -26,6 +29,8 @@ def add_mods(mods): mod_info = json.load(open(info)) for e in mod_info: if e["type"] == "MOD_INFO": + if not do_lua and "lua_api_version" in e: + continue ident = e["id"] if not ident in blacklist: all_mod_dependencies[ident] = e.get("dependencies", []) diff --git a/build-scripts/requirements.sh b/build-scripts/requirements.sh index a8d3fb9c36ae..6b228a0e9eb6 100644 --- a/build-scripts/requirements.sh +++ b/build-scripts/requirements.sh @@ -8,13 +8,24 @@ set -x echo "::add-matcher::build-scripts/problem-matchers/catch2.json" echo "::add-matcher::build-scripts/problem-matchers/debugmsg.json" +if [[ "$LIBBACKTRACE" == "1" ]]; then + git clone https://github.com/ianlancetaylor/libbacktrace.git + ( + cd libbacktrace + git checkout 4d2dd0b172f2c9192f83ba93425f868f2a13c553 + ./configure + make -j$(nproc) + sudo make install + ) +fi + if [ -n "$CATA_CLANG_TIDY" ]; then pip install --user wheel --upgrade pip install --user 'lit==0.11.1' 'click==7.1.2' fi if [ -n "$LANGUAGES" ]; then - pip install --user polib + pip install --user polib luaparser fi # Influenced by https://github.com/zer0main/battleship/blob/master/build/windows/requirements.sh diff --git a/data/json/LOADING_ORDER.md b/data/json/LOADING_ORDER.md index 5459b38c5d31..9f48a405678e 100644 --- a/data/json/LOADING_ORDER.md +++ b/data/json/LOADING_ORDER.md @@ -1,18 +1,16 @@ -# JSON Loading Order # +# JSON Loading Order -All files here in data/json are read eventually, but the order in which they're -read can be important for objects with dependencies on other kinds of objects -(e.g. recipes depend on skills). Ensuring the proper loading order will prevent -surprises that, most often, manifest as crash-to-desktop with segfault (a very -bad thing). +All files here in data/json are read eventually, but the order in which they're read can be +important for objects with dependencies on other kinds of objects (e.g. recipes depend on skills). +Ensuring the proper loading order will prevent surprises that, most often, manifest as +crash-to-desktop with segfault (a very bad thing). -The way Cataclysm finds and loads json files is by running a breadth-first -search in the tree data/json/. This means `data/json/whatever.json` will -**always** be read before `data/json/subdir/whatever.json`. This tells us how to -ensure dependency loading order. +The way Cataclysm finds and loads json files is by running a breadth-first search in the tree +data/json/. This means `data/json/whatever.json` will **always** be read before +`data/json/subdir/whatever.json`. This tells us how to ensure dependency loading order. -For instance, if you have scenarios that depend on professions that depend on -skills, you'll want a directory structure such as the following: +For instance, if you have scenarios that depend on professions that depend on skills, you'll want a +directory structure such as the following: ``` data/json/ @@ -23,13 +21,12 @@ data/json/ scenarios.json ``` -Which results in a loading order of: `skills.json` then `professions.json` and -then `scenarios.json`. +Which results in a loading order of: `skills.json` then `professions.json` and then +`scenarios.json`. -## Same-depth loading order ## +## Same-depth loading order -Note that, when files (or directories) are at the same depth -(i.e. all in `data/json/`), they will be read in lexical order, which is -more or less equivalent to alphabetical order for file names that use only -ascii characters. For UTF-8 or otherwise non-ascii file names, the names will be -ordered by codepoint. +Note that, when files (or directories) are at the same depth (i.e. all in `data/json/`), they will +be read in lexical order, which is more or less equivalent to alphabetical order for file names that +use only ascii characters. For UTF-8 or otherwise non-ascii file names, the names will be ordered by +codepoint. diff --git a/data/json/bionics.json b/data/json/bionics.json index a9beb1da6749..bda06072ab01 100644 --- a/data/json/bionics.json +++ b/data/json/bionics.json @@ -1278,10 +1278,21 @@ "id": "bio_perpetual_test", "type": "bionic", "name": { "str": "Perpetual Generator" }, - "description": "Installed within you is a perpetual generator powered by nonsensoleum. When activated it's power gen doubles. If you are seeing this, you'd better be debugging.", + "description": "Installed within you is a perpetual generator powered by nonsensoleum. When activated its power gen doubles. If you are seeing this, you'd better be debugging.", "fuel_options": [ "nonsensoleum" ], - "passive_fuel_efficiency": 1.0, - "fuel_efficiency": 2.0, + "passive_fuel_efficiency": 1, + "fuel_efficiency": 2, + "time": 1, + "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_TOGGLED" ] + }, + { + "id": "debug_bio_fuel_cell", + "type": "bionic", + "name": { "str": "Debug Fuel Cell CBM" }, + "description": "The power of the sun, in the palm of my hand! Installed within you is a perpetual generator powered by nonsensoleum. When activated its power gen doubles. If you are seeing this, you'd better be debugging.", + "fuel_options": [ "nonsensoleum" ], + "passive_fuel_efficiency": 10000, + "fuel_efficiency": 20000, "time": 1, "flags": [ "BIONIC_POWER_SOURCE", "BIONIC_TOGGLED" ] } diff --git a/data/json/furniture_and_terrain/terrain-manufactured.json b/data/json/furniture_and_terrain/terrain-manufactured.json index 355a4b89e607..e6840e358eff 100644 --- a/data/json/furniture_and_terrain/terrain-manufactured.json +++ b/data/json/furniture_and_terrain/terrain-manufactured.json @@ -411,6 +411,10 @@ "move_cost": 0, "coverage": 50, "flags": [ "TRANSPARENT", "MOUNTABLE", "PERMEABLE", "THIN_OBSTACLE", "MINEABLE" ], + "deconstruct": { + "ter_set": "t_bridge", + "items": [ { "item": "scrap", "count": [ 4, 8 ] }, { "item": "steel_plate", "count": [ 0, 2 ] } ] + }, "bash": { "str_min": 30, "str_max": 210, @@ -431,6 +435,14 @@ "move_cost": 0, "coverage": 50, "flags": [ "NOITEM", "REDUCE_SCENT", "MOUNTABLE" ], + "deconstruct": { + "ter_set": "t_bridge", + "items": [ + { "item": "steel_lump", "count": [ 0, 1 ] }, + { "item": "steel_chunk", "count": [ 1, 4 ] }, + { "item": "scrap", "count": [ 3, 7 ] } + ] + }, "bash": { "str_min": 20, "str_max": 150, diff --git a/data/json/itemgroups/Weapons_Mods_Ammo/everydaycarry_guns.json b/data/json/itemgroups/Weapons_Mods_Ammo/everydaycarry_guns.json new file mode 100644 index 000000000000..aa0bbd4bf836 --- /dev/null +++ b/data/json/itemgroups/Weapons_Mods_Ammo/everydaycarry_guns.json @@ -0,0 +1,1814 @@ +[ + { + "id": "everyday_glock_17", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "glock_17", "charges-min": 0, "charges-max": 15 }, + { "item": "glock17_17" }, + { "item": "glock17_17", "prob": 50 } + ] + }, + { + "id": "everyday_glock_19", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "glock_19", "charges-min": 0, "charges-max": 15 }, + { "item": "glockmag" }, + { "item": "glockmag", "prob": 50 } + ] + }, + { + "id": "everyday_glock_21", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "glock_21", "charges-min": 0, "charges-max": 15 }, + { "item": "glock_21mag" }, + { "item": "glock_21mag", "prob": 50 } + ] + }, + { + "id": "everyday_glock_22", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "glock_22", "charges-min": 0, "ammo-item": "40sw", "charges-max": 15 }, + { "item": "glock40mag" }, + { "item": "glock40mag", "prob": 50 } + ] + }, + { + "id": "everyday_glock_31", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "glock_31", "charges-min": 0, "charges-max": 15 }, + { "item": "glock40mag" }, + { "item": "glock40mag", "prob": 50 } + ] + }, + { + "id": "everyday_m1911", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m1911", "charges-min": 0, "charges-max": 7 }, { "item": "m1911mag" }, { "item": "m1911mag", "prob": 50 } ] + }, + { + "id": "everyday_m1911_MEU", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m1911_MEU", "charges-min": 0, "charges-max": 7 }, + { "item": "m1911mag" }, + { "item": "m1911mag", "prob": 50 } + ] + }, + { + "id": "everyday_m9", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m9", "charges-min": 0, "charges-max": 15 }, { "item": "m9mag" }, { "item": "m9mag", "prob": 50 } ] + }, + { + "id": "everyday_px4", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "px4", "charges-min": 0, "charges-max": 15 }, { "item": "px4mag" }, { "item": "px4mag", "prob": 50 } ] + }, + { + "id": "everyday_px4_40", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "px4_40", "charges-min": 0, "charges-max": 15 }, + { "item": "px4_40mag" }, + { "item": "px4_40mag", "prob": 50 } + ] + }, + { + "id": "everyday_sig_mosquito", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "sig_mosquito", "charges-min": 0, "charges-max": 10 }, + { "item": "mosquitomag" }, + { "item": "mosquitomag", "prob": 50 } + ] + }, + { + "id": "everyday_sw_22", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sw_22", "charges-min": 0, "charges-max": 10 }, { "item": "sw22mag" }, { "item": "sw22mag", "prob": 50 } ] + }, + { + "id": "everyday_taurus_spectrum", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "taurus_spectrum", "charges-min": 0, "charges-max": 6 }, + { "item": "taurus_spectrum_mag" }, + { "item": "taurus_spectrum_mag", "prob": 50 } + ] + }, + { + "id": "everyday_p226_357sig", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "p226_357sig", "charges-min": 0, "charges-max": 12 }, + { "item": "p226mag_12rd_357sig" }, + { "item": "p226mag_12rd_357sig", "prob": 50 } + ] + }, + { + "id": "everyday_p320_357sig", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "p320_357sig", "charges-min": 0, "charges-max": 13 }, + { "item": "p320mag_13rd_357sig" }, + { "item": "p320mag_13rd_357sig", "prob": 50 } + ] + }, + { + "id": "everyday_kp32", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "kp32", "charges-min": 0, "charges-max": 7 }, { "item": "kp32mag" }, { "item": "kp32mag", "prob": 50 } ] + }, + { + "id": "everyday_kp3at", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "kp3at", "charges-min": 0, "charges-max": 6 }, { "item": "kp3atmag" }, { "item": "kp3atmag", "prob": 50 } ] + }, + { + "id": "everyday_rugerlcp", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rugerlcp", "charges-min": 0, "charges-max": 6 }, + { "item": "rugerlcpmag" }, + { "item": "rugerlcpmag", "prob": 50 } + ] + }, + { + "id": "everyday_kpf9", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "kpf9", "charges-min": 0, "charges-max": 7 }, { "item": "kpf9mag" }, { "item": "kpf9mag", "prob": 50 } ] + }, + { + "id": "everyday_hi_power_9mm", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hi_power_9mm", "charges-min": 0, "charges-max": 15 }, + { "item": "bhp9mag_13rd" }, + { "item": "bhp9mag_13rd", "prob": 50 } + ] + }, + { + "id": "everyday_hi_power_40", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hi_power_40", "charges-min": 0, "charges-max": 10 }, + { "item": "bhp40mag" }, + { "item": "bhp40mag", "prob": 50 } + ] + }, + { + "id": "everyday_walther_p38", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "walther_p38", "charges-min": 0, "charges-max": 8 }, + { "item": "p38mag" }, + { "item": "p38mag", "prob": 50 } + ] + }, + { + "id": "everyday_walther_ppq_9mm", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "walther_ppq_9mm", "charges-min": 0, "charges-max": 17 }, + { "item": "ppq9mag_10rd" }, + { "item": "ppq9mag_10rd", "prob": 50 } + ] + }, + { + "id": "everyday_walther_ppq_40", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "walther_ppq_40", "charges-min": 0, "charges-max": 14 }, + { "item": "ppq40mag_10rd" }, + { "item": "ppq40mag_10rd", "prob": 50 } + ] + }, + { + "id": "everyday_walther_ppq_45", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "walther_ppq_45", "charges-min": 0, "charges-max": 12 }, + { "item": "ppq45mag" }, + { "item": "ppq45mag", "prob": 50 } + ] + }, + { + "id": "everyday_hptc9", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hptc9", "charges-min": 0, "charges-max": 15 }, + { "item": "hptc9mag_8rd" }, + { "item": "hptc9mag_8rd", "prob": 50 } + ] + }, + { + "id": "everyday_hptcf380", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hptcf380", "charges-min": 0, "charges-max": 10 }, + { "item": "hptcf380mag_8rd" }, + { "item": "hptcf380mag_8rd", "prob": 50 } + ] + }, + { + "id": "everyday_hptjcp", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hptjcp", "charges-min": 0, "charges-max": 10 }, + { "item": "hptjcpmag" }, + { "item": "hptjcpmag", "prob": 50 } + ] + }, + { + "id": "everyday_hptjhp", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hptjhp", "charges-min": 0, "charges-max": 9 }, + { "item": "hptjhpmag" }, + { "item": "hptjhpmag", "prob": 50 } + ] + }, + { + "id": "everyday_cz75", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "cz75", "charges-min": 0, "charges-max": 26 }, + { "item": "cz75mag_12rd" }, + { "item": "cz75mag_12rd", "prob": 50 } + ] + }, + { + "id": "everyday_walther_ccp", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "walther_ccp", "charges-min": 0, "charges-max": 8 }, + { "item": "ccpmag" }, + { "item": "ccpmag", "prob": 50 } + ] + }, + { + "id": "everyday_walther_p22", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "walther_p22", "charges-min": 0, "charges-max": 10 }, + { "item": "wp22mag" }, + { "item": "wp22mag", "prob": 50 } + ] + }, + { + "id": "everyday_90two", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "90two", "charges-min": 0, "charges-max": 15 }, { "item": "m9mag" }, { "item": "m9mag", "prob": 50 } ] + }, + { + "id": "everyday_90two40", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "90two40", "charges-min": 0, "charges-max": 12 }, + { "item": "90two40mag" }, + { "item": "90two40mag", "prob": 50 } + ] + }, + { + "id": "everyday_deagle_44", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "deagle_44", "charges-min": 0, "charges-max": 2 }, + { "item": "deaglemag" }, + { "item": "deaglemag", "prob": 50 } + ] + }, + { + "id": "everyday_m1911a1_38super", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m1911a1_38super", "charges-min": 0, "charges-max": 9 }, + { "item": "m1911mag_10rd_38super" }, + { "item": "m1911mag_10rd_38super", "prob": 50 } + ] + }, + { + "id": "everyday_fn57", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "fn57", "charges-min": 0, "charges-max": 20 }, { "item": "fn57mag" }, { "item": "fn57mag", "prob": 50 } ] + }, + { + "id": "everyday_sig_40", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "sig_40", "charges-min": 0, "charges-max": 12 }, + { "item": "sig40mag" }, + { "item": "sig40mag", "prob": 50 } + ] + }, + { + "id": "everyday_sig_p230", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "sig_p230", "charges-min": 0, "charges-max": 8 }, + { "item": "sigp230mag" }, + { "item": "sigp230mag", "prob": 50 } + ] + }, + { + "id": "everyday_usp_45", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "usp_45", "charges-min": 0, "charges-max": 12 }, + { "item": "usp45mag" }, + { "item": "usp45mag", "prob": 50 } + ] + }, + { + "id": "everyday_usp_9mm", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "usp_9mm", "charges-min": 0, "charges-max": 15 }, { "item": "usp9mag" }, { "item": "usp9mag", "prob": 50 } ] + }, + { + "id": "everyday_draco", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "draco", "charges-min": 0, "charges-max": 30 }, { "item": "akmag10" }, { "item": "akmag10", "prob": 50 } ] + }, + { + "id": "everyday_m17", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m17", "charges-min": 0, "charges-max": 17 }, + { "item": "p320mag_17rd_9x19mm" }, + { "item": "p320mag_17rd_9x19mm", "prob": 50 } + ] + }, + { + "id": "everyday_glock_18c", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "glock_18c", "charges-min": 0, "charges-max": 17 }, + { "item": "glock17_17" }, + { "item": "glock17_17", "prob": 50 } + ] + }, + { + "id": "everyday_mk23", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mk23", "charges-min": 0, "charges-max": 12 }, { "item": "usp45mag" }, { "item": "usp45mag", "prob": 50 } ] + }, + { + "id": "everyday_tokarev", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "tokarev" }, { "item": "tokarevmag" }, { "item": "tokarevmag", "prob": 50 } ] + }, + { + "id": "everyday_walther_ppk", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "walther_ppk" }, { "item": "ppkmag" }, { "item": "ppkmag", "prob": 50 } ] + }, + { + "id": "everyday_rm103a_pistol", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "rm103a_pistol" }, { "item": "8x40_10_mag" }, { "item": "8x40_10_mag", "prob": 50 } ] + }, + { + "id": "everyday_af2011a1_38super", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "af2011a1_38super" }, { "item": "af2011a1mag" }, { "item": "af2011a1mag", "prob": 50 } ] + }, + { + "id": "everyday_m1911-460", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m1911-460", "charges-min": 0, "charges-max": 7 }, + { "item": "m1911mag" }, + { "item": "m1911mag", "prob": 50 } + ] + }, + { + "id": "everyday_makarov", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "makarov", "charges-min": 0, "charges-max": 8 }, + { "item": "makarovmag" }, + { "item": "makarovmag", "prob": 50 } + ] + }, + { + "id": "everyday_hk_mp5_semi_pistol", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hk_mp5_semi_pistol", "charges-min": 0, "charges-max": 30 }, + { "item": "mp5mag" }, + { "item": "mp5mag", "prob": 50 } + ] + }, + { + "id": "everyday_calico", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "calico", "charges-min": 0, "charges-max": 50 }, + { "item": "calicomag" }, + { "item": "calicomag", "prob": 50 } + ] + }, + { + "id": "everyday_fn_p90", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "fn_p90", "charges-min": 0, "charges-max": 50 }, + { "item": "fnp90mag" }, + { "item": "fnp90mag", "prob": 50 } + ] + }, + { + "id": "everyday_tommygun", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "tommygun", "charges-min": 0, "charges-max": 20 }, + { "item": "thompson_mag" }, + { "item": "thompson_mag", "prob": 50 } + ] + }, + { + "id": "everyday_sten", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sten", "charges-min": 0, "charges-max": 32 }, { "item": "stenmag" }, { "item": "stenmag", "prob": 50 } ] + }, + { + "id": "everyday_uzi", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "uzi", "charges-min": 0, "charges-max": 32 }, { "item": "uzimag" }, { "item": "uzimag", "prob": 50 } ] + }, + { + "id": "everyday_hk_mp5", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "hk_mp5", "charges-min": 0, "charges-max": 30 }, { "item": "mp5mag" }, { "item": "mp5mag", "prob": 50 } ] + }, + { + "id": "everyday_hk_mp5sd", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "hk_mp5", "charges-min": 0, "charges-max": 30 }, { "item": "mp5mag" }, { "item": "mp5mag", "prob": 50 } ] + }, + { + "id": "everyday_hk_ump45", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hk_ump45", "charges-min": 0, "charges-max": 25 }, + { "item": "ump45mag" }, + { "item": "ump45mag", "prob": 50 } + ] + }, + { + "id": "everyday_mac_10", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "mac_10", "charges-min": 0, "charges-max": 30 }, + { "item": "mac10mag" }, + { "item": "mac10mag", "prob": 50 } + ] + }, + { + "id": "everyday_mac_11", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "mac_11", "charges-min": 0, "charges-max": 32 }, + { "item": "mac11mag" }, + { "item": "mac11mag", "prob": 50 } + ] + }, + { + "id": "everyday_TDI", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "TDI", "charges-min": 0, "charges-max": 30 }, { "item": "tdi_mag" }, { "item": "tdi_mag", "prob": 50 } ] + }, + { + "id": "everyday_american_180", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "american_180", "charges-min": 0, "charges-max": 100 }, + { "item": "a180mag" }, + { "item": "a180mag", "prob": 50 } + ] + }, + { + "id": "everyday_briefcase_smg", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "briefcase_smg", "charges-min": 0, "charges-max": 30 }, + { "item": "mp5mag" }, + { "item": "mp5mag", "prob": 50 } + ] + }, + { + "id": "everyday_tec9", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "tec9", "charges-min": 0, "charges-max": 30 }, { "item": "tec9mag" }, { "item": "tec9mag", "prob": 50 } ] + }, + { + "id": "everyday_hk_mp7", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "hk_mp7", "charges-min": 0, "charges-max": 20 }, { "item": "hk46mag" }, { "item": "hk46mag", "prob": 50 } ] + }, + { + "id": "everyday_rm2000_smg", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm2000_smg", "charges-min": 0, "charges-max": 10 }, + { "item": "8x40_10_mag" }, + { "item": "8x40_10_mag", "prob": 50 } + ] + }, + { + "id": "everyday_hk_mp5k", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "hk_mp5k", "charges-min": 0, "charges-max": 30 }, { "item": "mp5mag" }, { "item": "mp5mag", "prob": 50 } ] + }, + { + "id": "everyday_browning_blr", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "browning_blr", "charges-min": 0, "charges-max": 4 }, + { "item": "blrmag" }, + { "item": "blrmag", "prob": 50 } + ] + }, + { + "id": "everyday_ar_pistol", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ar_pistol", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag10" }, + { "item": "stanag10", "prob": 50 } + ] + }, + { + "id": "everyday_garand", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "garand", "charges-min": 0, "charges-max": 8 }, + { "item": "garandclip" }, + { "item": "garandclip", "prob": 50 } + ] + }, + { + "id": "everyday_ar10", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ar10", "charges-min": 0, "charges-max": 20 }, + { "item": "ar10mag_20rd" }, + { "item": "ar10mag_20rd", "prob": 50 } + ] + }, + { + "id": "everyday_ar15", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ar15", "charges-min": 0, "charges-max": 30 }, { "item": "stanag10" }, { "item": "stanag10", "prob": 50 } ] + }, + { + "id": "everyday_cx4", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "cx4", "charges-min": 0, "charges-max": 15 }, { "item": "m9mag" }, { "item": "m9mag", "prob": 50 } ] + }, + { + "id": "everyday_ksub2000", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ksub2000", "charges-min": 0, "charges-max": 15 }, + { "item": "glockmag" }, + { "item": "glockmag", "prob": 50 } + ] + }, + { + "id": "everyday_m1a", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m1a", "charges-min": 0, "charges-max": 5 }, + { "item": "m14smallmag" }, + { "item": "m14smallmag", "prob": 50 } + ] + }, + { + "id": "everyday_ruger_1022", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ruger_1022", "charges-min": 0, "charges-max": 10 }, + { "item": "ruger1022mag" }, + { "item": "ruger1022mag", "prob": 50 } + ] + }, + { + "id": "everyday_ruger_mini", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ruger_mini", "charges-min": 0, "charges-max": 5 }, + { "item": "ruger10" }, + { "item": "ruger10", "prob": 50 } + ] + }, + { + "id": "everyday_aksemi", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "1895sbl", "charges-min": 0, "charges-max": 30 }, { "item": "akmag10" }, { "item": "akmag10", "prob": 50 } ] + }, + { + "id": "everyday_fn_fal", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "fn_fal", "charges-min": 0, "charges-max": 20 }, { "item": "falmag" }, { "item": "falmag", "prob": 50 } ] + }, + { + "id": "everyday_hk_g3", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "hk_g3", "charges-min": 0, "charges-max": 20 }, { "item": "g3mag" }, { "item": "g3mag", "prob": 50 } ] + }, + { + "id": "everyday_hk_g36", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hk_g36", "charges-min": 0, "charges-max": 30 }, + { "item": "g36mag_30rd" }, + { "item": "g36mag_30rd", "prob": 50 } + ] + }, + { + "id": "everyday_m14ebr", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m14ebr", "charges-min": 0, "charges-max": 20 }, { "item": "m14mag" }, { "item": "m14mag", "prob": 50 } ] + }, + { + "id": "everyday_m4a1", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m4a1", "charges-min": 0, "charges-max": 30 }, { "item": "stanag30" }, { "item": "stanag30", "prob": 50 } ] + }, + { + "id": "everyday_m1918", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m1918", "charges-min": 0, "charges-max": 20 }, { "item": "m1918mag" }, { "item": "m1918mag", "prob": 50 } ] + }, + { + "id": "everyday_hk417_13", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "hk417_13", "charges-min": 0, "charges-max": 20 }, + { "item": "hk417mag_20rd" }, + { "item": "hk417mag_20rd", "prob": 50 } + ] + }, + { + "id": "everyday_iwi_tavor_x95_300blk", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "iwi_tavor_x95_300blk", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 } + ] + }, + { + "id": "everyday_h&k416a5", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "h&k416a5", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 } + ] + }, + { + "id": "everyday_m27iar", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m27iar", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 } + ] + }, + { + "id": "everyday_scar_l", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "scar_l", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 } + ] + }, + { + "id": "everyday_m107a1", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m107a1", "charges-min": 0, "charges-max": 10 }, + { "item": "m107a1mag" }, + { "item": "m107a1mag", "prob": 50 } + ] + }, + { + "id": "everyday_tac50", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "tac50", "charges-min": 0, "charges-max": 5 }, { "item": "tac50mag" }, { "item": "tac50mag", "prob": 50 } ] + }, + { + "id": "everyday_m2010", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m2010", "charges-min": 0, "charges-max": 5 }, { "item": "m2010mag" }, { "item": "m2010mag", "prob": 50 } ] + }, + { + "id": "everyday_rm11b_sniper_rifle", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm11b_sniper_rifle", "charges-min": 0, "charges-max": 10 }, + { "item": "8x40_10_mag" }, + { "item": "8x40_10_mag", "prob": 50 } + ] + }, + { + "id": "everyday_rm298", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm298", "charges-min": 0, "charges-max": 100 }, + { "item": "8x40_250_mag" }, + { "item": "8x40_250_mag", "prob": 50 } + ] + }, + { + "id": "everyday_rm51_assault_rifle", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm51_assault_rifle", "charges-min": 0, "charges-max": 50 }, + { "item": "8x40_50_mag" }, + { "item": "8x40_50_mag", "prob": 50 } + ] + }, + { + "id": "everyday_rm614_lmg", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm614_lmg", "charges-min": 0, "charges-max": 100 }, + { "item": "8x40_250_mag" }, + { "item": "8x40_250_mag", "prob": 50 } + ] + }, + { + "id": "everyday_rm88_battle_rifle", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm88_battle_rifle", "charges-min": 0, "charges-max": 50 }, + { "item": "8x40_50_mag" }, + { "item": "8x40_50_mag", "prob": 50 } + ] + }, + { + "id": "everyday_sig552", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "sig552", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 } + ] + }, + { + "id": "everyday_scar_h", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "scar_h", "charges-min": 0, "charges-max": 20 }, + { "item": "scarhmag" }, + { "item": "scarhmag", "prob": 50 } + ] + }, + { + "id": "everyday_m110a1", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "m110a1", "charges-min": 0, "charges-max": 20 }, + { "item": "hk417mag_20rd" }, + { "item": "hk417mag_20rd", "prob": 50 } + ] + }, + { + "id": "everyday_acr_300blk", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "acr_300blk", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 } + ] + }, + { + "id": "everyday_ak47", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ak47", "charges-min": 0, "charges-max": 30 }, { "item": "akmag10" }, { "item": "akmag10", "prob": 50 } ] + }, + { + "id": "everyday_ak74", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ak74", "charges-min": 0, "charges-max": 30 }, { "item": "ak74mag" }, { "item": "ak74mag", "prob": 50 } ] + }, + { + "id": "everyday_famas", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "famas", "charges-min": 0, "charges-max": 25 }, { "item": "famasmag" }, { "item": "famasmag", "prob": 50 } ] + }, + { + "id": "everyday_oa93", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "oa93", "charges-min": 0, "charges-max": 30 }, { "item": "stanag10" }, { "item": "stanag10", "prob": 50 } ] + }, + { + "id": "everyday_steyr_aug", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "steyr_aug", "charges-min": 0, "charges-max": 30 }, + { "item": "augmag_10rd" }, + { "item": "augmag_10rd", "prob": 50 } + ] + }, + { + "id": "everyday_arx160", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "arx160", "charges-min": 0, "charges-max": 30 }, { "item": "akmag10" }, { "item": "akmag10", "prob": 50 } ] + }, + { + "id": "everyday_rm20", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm20", "charges-min": 0, "charges-max": 20 }, + { "item": "20x66_20_mag" }, + { "item": "20x66_20_mag", "prob": 50 } + ] + }, + { + "id": "everyday_saiga_12", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "saiga_12", "charges-min": 0, "charges-max": 10 }, + { "item": "saiga10mag" }, + { "item": "saiga10mag", "prob": 50 } + ] + }, + { + "id": "everyday_saiga_410", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "saiga_410", "charges-min": 0, "charges-max": 10 }, + { "item": "saiga410mag_10rd" }, + { "item": "saiga410mag_10rd", "prob": 50 } + ] + }, + { + "id": "everyday_ruger_lcr_38", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ruger_lcr_38", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_38" } ] + }, + { + "id": "everyday_sw_610", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sw_610", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_10mm" } ] + }, + { + "id": "everyday_sw_619", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sw_619", "charges-min": 0, "charges-max": 7 }, { "group": "on_hand_38" } ] + }, + { + "id": "everyday_model_10_revolver", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "model_10_revolver", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_38" } ] + }, + { + "id": "everyday_bond_410", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "bond_410", "charges-min": 0, "charges-max": 2 }, { "group": "on_hand_45colt" } ] + }, + { + "id": "everyday_ruger_lcr_22", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ruger_lcr_22", "charges-min": 0, "charges-max": 8 }, { "group": "on_hand_22" } ] + }, + { + "id": "everyday_ruger_redhawk", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ruger_redhawk", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_44" } ] + }, + { + "id": "everyday_sw_500", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sw_500", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_500" } ] + }, + { + "id": "everyday_sw629", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sw629", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_44" } ] + }, + { + "id": "everyday_bfr", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "bfr" }, { "group": "on_hand_4570" } ] + }, + { + "id": "everyday_moss_brownie", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "moss_brownie" }, { "group": "on_hand_22" } ] + }, + { + "id": "everyday_raging_bull", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "raging_bull" }, { "group": "on_hand_454" } ] + }, + { + "id": "everyday_raging_judge", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "raging_judge" }, { "group": "on_hand_454" } ] + }, + { + "id": "everyday_cop_38", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "cop_38", "charges-min": 0, "charges-max": 4 }, { "group": "on_hand_38" } ] + }, + { + "id": "everyday_lemat_revolver", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "lemat_revolver", "charges-min": 0, "charges-max": 9 }, { "group": "on_hand_44paper" } ] + }, + { + "id": "everyday_pistol_flintlock", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "pistol_flintlock" }, { "group": "on_hand_flintlock" } ] + }, + { + "id": "everyday_colt_saa", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "colt_saa", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_45colt" } ] + }, + { + "id": "everyday_marlin_9a", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "marlin_9a", "charges-min": 0, "charges-max": 19 }, { "group": "on_hand_22" } ] + }, + { + "id": "everyday_mosin44", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mosin44", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_762R" } ] + }, + { + "id": "everyday_mosin91_30", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mosin91_30", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_762R" } ] + }, + { + "id": "everyday_remington700_270", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "remington700_270", "charges-min": 0, "charges-max": 4 }, { "group": "on_hand_270win" } ] + }, + { + "id": "everyday_remington_700", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "remington_700", "charges-min": 0, "charges-max": 4 }, { "group": "on_hand_3006" } ] + }, + { + "id": "everyday_sks", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sks", "charges-min": 0, "charges-max": 10 }, { "group": "on_hand_762" } ] + }, + { + "id": "everyday_win70", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "win70", "charges-min": 0, "charges-max": 3 }, { "group": "on_hand_300" } ] + }, + { + "id": "everyday_1895sbl", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "1895sbl", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_4570" } ] + }, + { + "id": "everyday_colt_lightning", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "colt_lightning", "charges-min": 0, "charges-max": 14 }, { "group": "on_hand_45colt" } ] + }, + { + "id": "everyday_henry_big_boy", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "henry_big_boy", "charges-min": 0, "charges-max": 10 }, { "group": "on_hand_44" } ] + }, + { + "id": "everyday_M24", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "M24", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_308" } ] + }, + { + "id": "everyday_m1903", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m1903", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_3006" } ] + }, + { + "id": "everyday_mosin44_ebr", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mosin44_ebr", "prob": 1, "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_762R" } ] + }, + { + "id": "everyday_mosin91_30_ebr", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mosin91_30_ebr", "prob": 1, "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_762R" } ] + }, + { + "id": "everyday_savage_111f", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "savage_111f", "charges-min": 0, "charges-max": 3 }, { "group": "on_hand_308" } ] + }, + { + "id": "everyday_sharps", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "sharps", "charges-min": 0, "charges-max": 1 }, { "group": "on_hand_4570" } ] + }, + { + "id": "everyday_weatherby_5", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "weatherby_5", "charges-min": 0, "charges-max": 3 }, { "group": "on_hand_300" } ] + }, + { + "id": "everyday_m134", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m134", "charges-min": 0, "charges-max": 100 }, { "group": "on_hand_308" } ] + }, + { + "id": "everyday_m240", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m240", "charges-min": 0, "charges-max": 100 }, { "group": "on_hand_308" } ] + }, + { + "id": "everyday_m249", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m249", "charges-min": 0, "charges-max": 100 }, { "group": "on_hand_223" } ] + }, + { + "id": "everyday_m60", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m60", "charges-min": 0, "charges-max": 100 }, { "group": "on_hand_308" } ] + }, + { + "id": "everyday_bh_m89", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "bh_m89", "charges-min": 0, "charges-max": 7 }, { "group": "on_hand_500" } ] + }, + { + "id": "everyday_bfg50", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "bh_m89", "charges-min": 0, "charges-max": 1 }, { "group": "on_hand_50" } ] + }, + { + "id": "everyday_carbine_flintlock", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "carbine_flintlock", "charges-min": 0, "charges-max": 1 }, { "group": "on_hand_flintlock" } ] + }, + { + "id": "everyday_rifle_flintlock", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "rifle_flintlock" }, { "group": "on_hand_flintlock" } ] + }, + { + "id": "everyday_trex_gun", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "trex_gun", "charges-min": 0, "charges-max": 1 }, { "group": "on_hand_700nx" } ] + }, + { + "id": "everyday_mossberg_500", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mossberg_500", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_remington_870", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "remington_870", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_mossberg_500_security", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mossberg_500_security", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_remington_870_express", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "remington_870_express", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_browning_a5", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "browning_a5", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_remington_1100", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "remington_1100", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_mossberg_930", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mossberg_930", "charges-min": 0, "charges-max": 6 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_shotgun_410", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "shotgun_410", "charges-min": 0, "charges-max": 1 }, { "group": "on_hand_410shot" } ] + }, + { + "id": "everyday_shotgun_d", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "shotgun_d", "charges-min": 0, "charges-max": 2 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_shotgun_s", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "shotgun_s", "charges-min": 0, "charges-max": 1 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_ksg", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ksg", "charges-min": 0, "charges-max": 7 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_ksg-25", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ksg", "charges-min": 0, "charges-max": 12 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_tavor_12", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "tavor_12", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_m1014", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "m1014", "charges-min": 0, "charges-max": 8 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_SPAS_12", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "SPAS_12", "charges-min": 0, "charges-max": 9 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_mossberg_590", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "mossberg_590", "charges-min": 0, "charges-max": 9 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_remington_870_breacher", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "remington_870_breacher", "charges-min": 0, "charges-max": 4 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_streetsweeper", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "streetsweeper", "charges-min": 0, "charges-max": 12 }, { "group": "on_hand_shot" } ] + }, + { + "id": "everyday_rm228", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm228", "charges-min": 0, "charges-max": 10 }, + { "item": "20x66_10_mag" }, + { "item": "20x66_10_mag", "prob": 50 } + ] + }, + { + "id": "everyday_an94", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "an94", "charges-min": 0, "charges-max": 30 }, { "item": "ak74mag" }, { "item": "ak74mag", "prob": 50 } ] + }, + { + "id": "everyday_USAS_12", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "USAS_12", "charges-min": 0, "charges-max": 10 }, + { "item": "USAS10mag" }, + { "item": "USAS10mag", "prob": 50 } + ] + }, + { + "id": "everyday_as50", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "as50", "charges-min": 0, "charges-max": 10 }, { "item": "as50mag" }, { "item": "as50mag", "prob": 50 } ] + }, + { + "id": "everyday_needlepistol", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "needlepistol", "charges-min": 0, "charges-max": 50 }, + { "item": "5x50_50_mag" }, + { "item": "5x50_50_mag", "prob": 50 } + ] + }, + { + "id": "everyday_rm99_pistol", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm99_pistol", "charges-min": 0, "charges-max": 50 }, + { "item": "8x40_50_mag" }, + { "item": "8x40_50_mag", "prob": 50 } + ] + }, + { + "id": "everyday_ppsh", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "ppsh", "charges-min": 0, "charges-max": 35 }, { "item": "ppshmag" }, { "item": "ppshmag", "prob": 50 } ] + }, + { + "id": "everyday_skorpion_61", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "skorpion_61", "charges-min": 0, "charges-max": 20 }, + { "item": "skorpion61mag" }, + { "item": "skorpion61mag", "prob": 50 } + ] + }, + { + "id": "everyday_skorpion_82", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "skorpion_82", "charges-min": 0, "charges-max": 20 }, + { "item": "skorpion82mag" }, + { "item": "skorpion82mag", "prob": 50 } + ] + }, + { + "id": "everyday_acr", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "acr", "charges-min": 0, "charges-max": 30 }, { "item": "stanag30" }, { "item": "stanag30", "prob": 50 } ] + }, + { + "id": "everyday_ar15_retool_300blk", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ar15_retool_300blk", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 } + ] + }, + { + "id": "everyday_needlegun", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "needlegun", "charges-min": 0, "charges-max": 100 }, + { "item": "5x50_100_mag" }, + { "item": "5x50_100_mag", "prob": 50 } + ] + }, + { + "id": "everyday_rm120c", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "rm120c", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_20x66mm" } ] + } +] diff --git a/data/json/itemgroups/Weapons_Mods_Ammo/guns.json b/data/json/itemgroups/Weapons_Mods_Ammo/guns.json index 3cfaa64c504e..fa4a3c75438c 100644 --- a/data/json/itemgroups/Weapons_Mods_Ammo/guns.json +++ b/data/json/itemgroups/Weapons_Mods_Ammo/guns.json @@ -41,6 +41,48 @@ { "group": "nested_walther_p22", "prob": 13 } ] }, + { + "type": "item_group", + "id": "carried_guns_pistol_common", + "//": "Pistols commonly owned by citizens and carried by them. If a gun has mags, it has no loose ammo. If it has no mags, it has loose ammo.", + "items": [ + { "group": "everyday_glock_17", "prob": 35 }, + { "group": "everyday_glock_19", "prob": 50 }, + { "group": "everyday_glock_21", "prob": 8 }, + { "group": "everyday_glock_22", "prob": 35 }, + { "group": "everyday_glock_31", "prob": 15 }, + { "group": "everyday_m1911", "prob": 50 }, + { "group": "everyday_m9", "prob": 30 }, + { "group": "everyday_px4", "prob": 24 }, + { "group": "everyday_px4_40", "prob": 20 }, + { "group": "everyday_ruger_lcr_38", "prob": 10 }, + { "group": "everyday_sig_mosquito", "prob": 15 }, + { "group": "everyday_sw_22", "prob": 15 }, + { "group": "everyday_sw_610", "prob": 20 }, + { "group": "everyday_sw_619", "prob": 25 }, + { "group": "everyday_model_10_revolver", "prob": 20 }, + { "group": "everyday_taurus_spectrum", "prob": 15 }, + { "group": "everyday_p226_357sig", "prob": 20 }, + { "group": "everyday_p320_357sig", "prob": 10 }, + { "group": "everyday_kp32", "prob": 10 }, + { "group": "everyday_kp3at", "prob": 35 }, + { "group": "everyday_rugerlcp", "prob": 35 }, + { "group": "everyday_kpf9", "prob": 35 }, + { "group": "everyday_hi_power_9mm", "prob": 5 }, + { "group": "everyday_hi_power_40", "prob": 3 }, + { "group": "everyday_walther_p38", "prob": 2 }, + { "group": "everyday_walther_ppq_9mm", "prob": 9 }, + { "group": "everyday_walther_ppq_40", "prob": 5 }, + { "group": "everyday_walther_ppq_45", "prob": 3 }, + { "group": "everyday_hptc9", "prob": 3 }, + { "group": "everyday_hptcf380", "prob": 2 }, + { "group": "everyday_hptjcp", "prob": 1 }, + { "group": "everyday_hptjhp", "prob": 1 }, + { "group": "everyday_cz75", "prob": 18 }, + { "group": "everyday_walther_ccp", "prob": 8 }, + { "group": "everyday_walther_p22", "prob": 13 } + ] + }, { "type": "item_group", "id": "guns_pistol_common_display", @@ -103,6 +145,28 @@ { "group": "nested_draco", "prob": 30 } ] }, + { + "type": "item_group", + "id": "carried_guns_pistol_rare", + "//": "Less common pistols including those only used by police/paramilitary forces. As these are carried, they either have mags OR loose ammo rather than both", + "items": [ + { "group": "everyday_90two", "prob": 25 }, + { "group": "everyday_90two40", "prob": 10 }, + { "group": "everyday_bond_410", "prob": 20 }, + { "group": "everyday_deagle_44", "prob": 35 }, + { "group": "everyday_m1911a1_38super", "prob": 25 }, + { "group": "everyday_fn57", "prob": 80 }, + { "group": "everyday_ruger_lcr_22", "prob": 35 }, + { "group": "everyday_ruger_redhawk", "prob": 25 }, + { "group": "everyday_sig_40", "prob": 35 }, + { "group": "everyday_sig_p230", "prob": 45 }, + { "group": "everyday_sw_500", "prob": 25 }, + { "group": "everyday_sw629", "prob": 40 }, + { "group": "everyday_usp_45", "prob": 70 }, + { "group": "everyday_usp_9mm", "prob": 120 }, + { "group": "everyday_draco", "prob": 30 } + ] + }, { "type": "item_group", "id": "guns_pistol_rare_display", @@ -134,10 +198,25 @@ { "group": "nested_usp_45", "prob": 15 }, { "group": "nested_m1911_MEU", "prob": 5 }, { "group": "nested_glock_19", "prob": 20 }, - { "item": "needlepistol", "prob": 45, "charges-min": 0, "charges-max": 50 }, + { "group": "nested_needlepistol", "prob": 45 }, { "group": "nested_rm103a_pistol", "prob": 35 } ] }, + { + "type": "item_group", + "id": "carried_guns_pistol_milspec", + "//": "Military specification pistols only ever carried by the military. Mags OR loose ammo", + "items": [ + { "group": "everyday_m17", "prob": 100 }, + { "group": "everyday_glock_18c", "prob": 70 }, + { "group": "everyday_mk23", "prob": 10 }, + { "group": "everyday_usp_45", "prob": 15 }, + { "group": "everyday_m1911_MEU", "prob": 5 }, + { "group": "everyday_glock_19", "prob": 20 }, + { "group": "everyday_needlepistol", "prob": 45 }, + { "group": "everyday_rm103a_pistol", "prob": 35 } + ] + }, { "type": "item_group", "id": "guns_pistol_obscure", @@ -153,12 +232,33 @@ { "group": "nested_pistol_flintlock", "prob": 150 }, { "group": "nested_raging_bull", "prob": 100 }, { "group": "nested_raging_judge", "prob": 20 }, - { "item": "rm99_pistol", "prob": 150, "charges-min": 0, "charges-max": 5 }, + { "group": "nested_rm99_pistol", "prob": 150 }, { "group": "nested_tokarev", "prob": 100 }, { "group": "nested_walther_ppk", "prob": 100 }, { "group": "nested_colt_saa", "prob": 150 } ] }, + { + "type": "item_group", + "id": "carried_guns_pistol_obscure", + "//": "Imported or otherwise very obscure pistols being carried, with either mags or loose ammo.", + "items": [ + { "group": "everyday_af2011a1_38super", "prob": 1 }, + { "group": "everyday_bfr", "prob": 100 }, + { "group": "everyday_cop_38", "prob": 100 }, + { "group": "everyday_m1911-460", "prob": 3 }, + { "group": "everyday_lemat_revolver", "prob": 150 }, + { "group": "everyday_makarov", "prob": 100 }, + { "group": "everyday_moss_brownie", "prob": 100 }, + { "group": "everyday_pistol_flintlock", "prob": 150 }, + { "group": "everyday_raging_bull", "prob": 100 }, + { "group": "everyday_raging_judge", "prob": 20 }, + { "group": "everyday_rm99_pistol", "prob": 150 }, + { "group": "everyday_tokarev", "prob": 100 }, + { "group": "everyday_walther_ppk", "prob": 100 }, + { "group": "everyday_colt_saa", "prob": 150 } + ] + }, { "type": "item_group", "id": "guns_pistol_improvised", @@ -180,6 +280,17 @@ { "group": "nested_uzi", "prob": 100 } ] }, + { + "type": "item_group", + "id": "carried_guns_smg_common", + "//": "SMGs commonly owned by citizens and carried. Also has either mags or loose ammo.", + "items": [ + { "group": "everyday_tommygun", "prob": 70 }, + { "group": "everyday_hk_mp5_semi_pistol", "prob": 70 }, + { "group": "everyday_sten", "prob": 100 }, + { "group": "everyday_uzi", "prob": 100 } + ] + }, { "type": "item_group", "id": "guns_smg_common_display", @@ -209,6 +320,24 @@ { "group": "nested_tec9", "prob": 50 } ] }, + { + "type": "item_group", + "id": "carried_guns_smg_rare", + "//": "Less common SMGs including those only carried by police/paramilitary forces. Either mags or loose ammo are included.", + "items": [ + { "group": "everyday_calico", "prob": 30 }, + { "group": "everyday_fn_p90", "prob": 50 }, + { "group": "everyday_hk_mp5", "prob": 100 }, + { "group": "everyday_hk_mp5sd", "prob": 5 }, + { "group": "everyday_hk_ump45", "prob": 30 }, + { "group": "everyday_mac_10", "prob": 40 }, + { "group": "everyday_mac_11", "prob": 20 }, + { "group": "everyday_TDI", "prob": 10 }, + { "group": "everyday_american_180", "prob": 50 }, + { "group": "everyday_briefcase_smg", "prob": 5 }, + { "group": "everyday_tec9", "prob": 50 } + ] + }, { "type": "item_group", "id": "guns_smg_rare_display", @@ -233,21 +362,44 @@ "//": "Military specification SMGs only ever found at military sites.", "items": [ { "group": "nested_hk_mp7", "prob": 100 }, - { "item": "needlegun", "prob": 30, "charges-min": 0, "charges-max": 50 }, + { "group": "nested_needlegun", "prob": 30 }, { "group": "nested_rm2000_smg", "prob": 50 }, { "group": "nested_hk_mp5", "prob": 100 }, { "group": "nested_hk_mp5k", "prob": 10 }, { "group": "nested_hk_mp5sd", "prob": 5 } ] }, + { + "type": "item_group", + "id": "carried_guns_smg_milspec", + "//": "Military specification SMGs only ever carried by the military. Comes with mags or loose ammo.", + "items": [ + { "group": "everyday_hk_mp7", "prob": 100 }, + { "group": "everyday_needlegun", "prob": 30 }, + { "group": "everyday_rm2000_smg", "prob": 50 }, + { "group": "everyday_hk_mp5", "prob": 100 }, + { "group": "everyday_hk_mp5k", "prob": 10 }, + { "group": "everyday_hk_mp5sd", "prob": 5 } + ] + }, { "type": "item_group", "id": "guns_smg_obscure", "//": "Imported or otherwise very obscure SMGs.", "items": [ - { "item": "ppsh", "prob": 150, "charges-min": 0, "charges-max": 35 }, - { "item": "skorpion_61", "prob": 100, "charges-min": 0, "charges-max": 20 }, - { "item": "skorpion_82", "prob": 100, "charges-min": 0, "charges-max": 20 } + { "group": "nested_ppsh", "prob": 150 }, + { "group": "nested_skorpion_61", "prob": 100 }, + { "group": "nested_skorpion_82", "prob": 100 } + ] + }, + { + "type": "item_group", + "id": "carried_guns_smg_obscure", + "//": "Imported or otherwise very obscure SMGs. Just mags, no loose ammo.", + "items": [ + { "group": "everyday_ppsh", "prob": 150 }, + { "group": "everyday_skorpion_61", "prob": 100 }, + { "group": "everyday_skorpion_82", "prob": 100 } ] }, { @@ -281,6 +433,31 @@ { "group": "nested_aksemi", "prob": 35 } ] }, + { + "type": "item_group", + "id": "carried_guns_rifle_common", + "//": "Rifles commonly owned by citizens and carried by them. Has mags or loose ammo.", + "items": [ + { "group": "everyday_browning_blr", "prob": 25 }, + { "group": "everyday_ar_pistol", "prob": 52 }, + { "group": "everyday_garand", "prob": 65 }, + { "group": "everyday_ar10", "prob": 20 }, + { "group": "everyday_ar15", "prob": 30 }, + { "group": "everyday_cx4", "prob": 45 }, + { "group": "everyday_ksub2000", "prob": 30 }, + { "group": "everyday_m1a", "prob": 50 }, + { "group": "everyday_marlin_9a", "prob": 80 }, + { "group": "everyday_mosin44", "prob": 15 }, + { "group": "everyday_mosin91_30", "prob": 25 }, + { "group": "everyday_remington700_270", "prob": 50 }, + { "group": "everyday_ruger_1022", "prob": 70 }, + { "group": "everyday_ruger_mini", "prob": 60 }, + { "group": "everyday_sks", "prob": 40 }, + { "group": "everyday_win70", "prob": 15 }, + { "group": "everyday_1895sbl", "prob": 15 }, + { "group": "everyday_aksemi", "prob": 35 } + ] + }, { "type": "item_group", "id": "guns_rifle_common_display", @@ -310,7 +487,7 @@ "id": "guns_rifle_rare", "//": "Less common rifles including those only used by police/paramilitary forces.", "items": [ - { "item": "acr", "prob": 25, "charges-min": 0, "charges-max": 30 }, + { "group": "nested_acr", "prob": 25 }, { "group": "nested_colt_lightning", "prob": 15 }, { "group": "nested_fn_fal", "prob": 40 }, { "group": "nested_hk_g3", "prob": 40 }, @@ -328,10 +505,37 @@ { "group": "nested_sharps", "prob": 15 }, { "group": "nested_weatherby_5", "prob": 15 }, { "group": "nested_hk417_13", "prob": 40 }, - { "item": "ar15_retool_300blk", "prob": 15, "charges-min": 0, "charges-max": 30 }, + { "group": "nested_ar15_retool_300blk", "prob": 15 }, { "group": "nested_iwi_tavor_x95_300blk", "prob": 10 } ] }, + { + "type": "item_group", + "id": "carried_guns_rifle_rare", + "//": "Less common rifles including those only carried by police/paramilitary forces. Served with mags or a side of loose ammo.", + "items": [ + { "group": "everyday_acr", "prob": 25 }, + { "group": "everyday_colt_lightning", "prob": 15 }, + { "group": "everyday_fn_fal", "prob": 40 }, + { "group": "everyday_hk_g3", "prob": 40 }, + { "group": "everyday_hk_g36", "prob": 30 }, + { "group": "everyday_henry_big_boy", "prob": 10 }, + { "group": "everyday_m14ebr", "prob": 15 }, + { "group": "everyday_M24", "prob": 15 }, + { "group": "everyday_m4a1", "prob": 45 }, + { "group": "everyday_m1903", "prob": 15 }, + { "group": "everyday_m1918", "prob": 30 }, + { "group": "everyday_mosin44_ebr", "prob": 10 }, + { "group": "everyday_mosin91_30_ebr", "prob": 20 }, + { "group": "everyday_remington_700", "prob": 20 }, + { "group": "everyday_savage_111f", "prob": 15 }, + { "group": "everyday_sharps", "prob": 15 }, + { "group": "everyday_weatherby_5", "prob": 15 }, + { "group": "everyday_hk417_13", "prob": 40 }, + { "group": "everyday_ar15_retool_300blk", "prob": 15 }, + { "group": "everyday_iwi_tavor_x95_300blk", "prob": 10 } + ] + }, { "type": "item_group", "id": "guns_rifle_rare_display", @@ -386,6 +590,33 @@ { "group": "nested_acr_300blk", "prob": 15 } ] }, + { + "type": "item_group", + "id": "carried_guns_rifle_milspec", + "//": "Military specification rifles only ever carried by the military. Issued with mags or loose ammo.", + "items": [ + { "group": "everyday_h&k416a5", "prob": 50 }, + { "group": "everyday_m107a1", "prob": 30 }, + { "group": "everyday_m134", "prob": 10 }, + { "group": "everyday_m14ebr", "prob": 10 }, + { "group": "everyday_tac50", "prob": 5 }, + { "group": "everyday_m2010", "prob": 20 }, + { "group": "everyday_m240", "prob": 15 }, + { "group": "everyday_m249", "prob": 25 }, + { "group": "everyday_m27iar", "prob": 50 }, + { "group": "everyday_m60", "prob": 15 }, + { "group": "everyday_rm11b_sniper_rifle", "prob": 15 }, + { "group": "everyday_rm298", "prob": 10 }, + { "group": "everyday_rm51_assault_rifle", "prob": 25 }, + { "group": "everyday_rm614_lmg", "prob": 10 }, + { "group": "everyday_rm88_battle_rifle", "prob": 25 }, + { "group": "everyday_sig552", "prob": 100 }, + { "group": "everyday_scar_l", "prob": 50 }, + { "group": "everyday_scar_h", "prob": 50 }, + { "group": "everyday_m110a1", "prob": 50 }, + { "group": "everyday_acr_300blk", "prob": 15 } + ] + }, { "type": "item_group", "id": "guns_bank_vault", @@ -405,13 +636,13 @@ { "group": "nested_rm88_battle_rifle", "prob": 10 }, { "group": "nested_rm103a_pistol", "prob": 10 }, { "group": "nested_m110a1", "prob": 10 }, - { "item": "needlegun", "prob": 10, "charges-min": 0, "charges-max": 50 }, - { "item": "needlepistol", "prob": 10, "charges-min": 0, "charges-max": 50 }, + { "group": "nested_needlegun", "prob": 10 }, + { "group": "nested_needlepistol", "prob": 10 }, { "group": "nested_ksg-25", "prob": 10 }, { "group": "nested_tavor_12", "prob": 10 }, { "group": "nested_SPAS_12", "prob": 10 }, - { "item": "rm120c", "prob": 10, "charges-min": 0, "charges-max": 5 }, - { "item": "rm228", "prob": 10, "charges-min": 0, "charges-max": 10 }, + { "group": "nested_rm120c", "prob": 10 }, + { "group": "nested_rm228", "prob": 10 }, { "group": "nested_deagle_44", "prob": 10 } ] }, @@ -433,7 +664,7 @@ "items": [ { "group": "nested_ak47", "prob": 100 }, { "group": "nested_ak74", "prob": 60 }, - { "item": "an94", "prob": 40, "charges-min": 0, "charges-max": 30 }, + { "group": "nested_an94", "prob": 40 }, { "group": "nested_bh_m89", "prob": 20 }, { "group": "nested_bfg50", "prob": 5 }, { "group": "nested_carbine_flintlock", "prob": 140 }, @@ -447,6 +678,27 @@ { "group": "nested_acr_300blk", "prob": 15 } ] }, + { + "type": "item_group", + "id": "carried_guns_rifle_obscure", + "//": "Imported or otherwise very obscure rifles. Comes with mags or loose ammo.", + "items": [ + { "group": "everyday_ak47", "prob": 100 }, + { "group": "everyday_ak74", "prob": 60 }, + { "group": "everyday_an94", "prob": 40 }, + { "group": "everyday_bh_m89", "prob": 20 }, + { "group": "everyday_bfg50", "prob": 5 }, + { "group": "everyday_carbine_flintlock", "prob": 140 }, + { "group": "everyday_famas", "prob": 1 }, + { "group": "everyday_rifle_flintlock", "prob": 180 }, + { "group": "everyday_oa93", "prob": 3 }, + { "group": "everyday_steyr_aug", "prob": 40 }, + { "group": "everyday_trex_gun", "prob": 60 }, + { "group": "everyday_arx160", "prob": 40 }, + { "group": "everyday_iwi_tavor_x95_300blk", "prob": 10 }, + { "group": "everyday_acr_300blk", "prob": 15 } + ] + }, { "type": "item_group", "id": "guns_rifle_improvised", @@ -475,6 +727,23 @@ { "group": "nested_shotgun_s", "prob": 30 } ] }, + { + "type": "item_group", + "id": "carried_guns_shotgun_common", + "//": "Shotguns commonly owned by citizens and carried for home defense. Has loose ammo, because these aren't the fancy mag-fed shotguns.", + "items": [ + { "group": "everyday_mossberg_500", "prob": 33 }, + { "group": "everyday_remington_870", "prob": 35 }, + { "group": "everyday_mossberg_500_security", "prob": 17 }, + { "group": "everyday_remington_870_express", "prob": 18 }, + { "group": "everyday_browning_a5", "prob": 14 }, + { "group": "everyday_remington_1100", "prob": 17 }, + { "group": "everyday_mossberg_930", "prob": 15 }, + { "group": "everyday_shotgun_410", "prob": 30 }, + { "group": "everyday_shotgun_d", "prob": 30 }, + { "group": "everyday_shotgun_s", "prob": 30 } + ] + }, { "type": "item_group", "id": "guns_shotgun_common_display", @@ -503,8 +772,23 @@ { "group": "nested_tavor_12", "prob": 5 }, { "group": "nested_m1014", "prob": 10 }, { "group": "nested_SPAS_12", "prob": 2 }, - { "item": "rm120c", "prob": 5, "charges-min": 0, "charges-max": 5 }, - { "item": "rm228", "prob": 5, "charges-min": 0, "charges-max": 10 } + { "group": "nested_rm120c", "prob": 5 }, + { "group": "nested_rm228", "prob": 5 } + ] + }, + { + "type": "item_group", + "id": "carried_guns_shotgun_rare", + "//": "Uncommon or rare shotguns in civilian possession. Comes with loose ammo, unless one of these actually has mags, then it'd have mags.", + "subtype": "distribution", + "entries": [ + { "group": "everyday_ksg", "prob": 50 }, + { "group": "everyday_ksg-25", "prob": 8 }, + { "group": "everyday_tavor_12", "prob": 5 }, + { "group": "everyday_m1014", "prob": 10 }, + { "group": "everyday_SPAS_12", "prob": 2 }, + { "group": "everyday_rm120c", "prob": 5 }, + { "group": "everyday_rm228", "prob": 5 } ] }, { @@ -563,6 +847,18 @@ { "group": "nested_m1014", "prob": 100 } ] }, + { + "type": "item_group", + "id": "carried_guns_shotgun_milspec", + "//": "Military shotguns currently in service. Might have mags, might have loose ammo.", + "items": [ + { "group": "everyday_rm20", "prob": 20 }, + { "group": "everyday_remington_870_express", "prob": 50 }, + { "group": "everyday_remington_870_breacher", "prob": 20 }, + { "group": "everyday_mossberg_590", "prob": 50 }, + { "group": "everyday_m1014", "prob": 100 } + ] + }, { "type": "item_group", "id": "guns_shotgun_obscure", @@ -570,10 +866,21 @@ "items": [ { "group": "nested_saiga_12", "prob": 50 }, { "group": "nested_streetsweeper", "prob": 4 }, - { "item": "USAS_12", "prob": 1, "charges-min": 0, "charges-max": 10 }, + { "group": "nested_USAS_12", "prob": 1 }, { "group": "nested_saiga_410", "prob": 40 } ] }, + { + "type": "item_group", + "id": "carried_guns_shotgun_obscure", + "//": "Imported or otherwise very obscure shotguns. Actually has a decent chance of having mags instead of loose ammo.", + "items": [ + { "group": "everyday_saiga_12", "prob": 50 }, + { "group": "everyday_streetsweeper", "prob": 4 }, + { "group": "everyday_USAS_12", "prob": 1 }, + { "group": "everyday_saiga_410", "prob": 40 } + ] + }, { "type": "item_group", "id": "guns_shotgun_improvised", @@ -756,6 +1063,31 @@ { "group": "nested_kpf9", "prob": 3 } ] }, + { + "type": "item_group", + "id": "carried_guns_cop", + "//": "Police issue weapons of all types. Carried, so they have mags or loose ammo.", + "items": [ + { "group": "everyday_ar15", "prob": 15 }, + { "group": "everyday_cx4", "prob": 20 }, + { "group": "everyday_fn57", "prob": 20 }, + { "group": "everyday_fn_p90", "prob": 5 }, + { "group": "everyday_glock_19", "prob": 15 }, + { "group": "everyday_glock_22", "prob": 20 }, + { "group": "everyday_hk_mp5", "prob": 10 }, + { "group": "everyday_m9", "prob": 5 }, + { "group": "everyday_mossberg_500", "prob": 15 }, + { "group": "everyday_remington_700", "prob": 5 }, + { "group": "everyday_remington_870", "prob": 20 }, + { "group": "everyday_sig_40", "prob": 20 }, + { "group": "everyday_usp_45", "prob": 10 }, + { "group": "everyday_usp_9mm", "prob": 10 }, + { "group": "everyday_kp32", "prob": 1 }, + { "group": "everyday_kp3at", "prob": 2 }, + { "group": "everyday_rugerlcp", "prob": 2 }, + { "group": "everyday_kpf9", "prob": 3 } + ] + }, { "type": "item_group", "id": "guns_swat", @@ -768,28 +1100,45 @@ { "group": "nested_hk_mp5sd", "prob": 5 }, { "group": "nested_m1014", "prob": 10 }, { "group": "nested_m4a1", "prob": 35 }, - { "item": "as50", "prob": 5, "charges-min": 0, "charges-max": 10 }, - { "item": "USAS_12", "prob": 1, "charges-min": 0, "charges-max": 10 }, + { "group": "nested_as50", "prob": 5 }, + { "group": "nested_USAS_12", "prob": 1 }, { "group": "nested_hk417_13", "prob": 30 } ] }, + { + "type": "item_group", + "id": "carried_guns_swat", + "//": "Guns issued to paramilitary forces in addition to standard police issue. Comes with mags or loose ammo.", + "items": [ + { "group": "guns_cop", "prob": 100 }, + { "group": "everyday_hk_ump45", "prob": 15 }, + { "group": "everyday_hk_mp5", "prob": 50 }, + { "group": "everyday_hk_mp5k", "prob": 10 }, + { "group": "everyday_hk_mp5sd", "prob": 5 }, + { "group": "everyday_m1014", "prob": 10 }, + { "group": "everyday_m4a1", "prob": 35 }, + { "group": "everyday_as50", "prob": 5 }, + { "group": "everyday_USAS_12", "prob": 1 }, + { "group": "everyday_hk417_13", "prob": 30 } + ] + }, { "type": "item_group", "id": "guns_survival", "//": "Guns typically carried by survivors, either improvised or thematically appropriate.", "items": [ { "group": "guns_improvised", "prob": 200 }, - { "group": "nested_ar15", "prob": 5 }, - { "group": "nested_ar_pistol", "prob": 3 }, - { "group": "nested_mossberg_500", "prob": 5 }, - { "group": "nested_remington_870", "prob": 5 }, - { "group": "nested_ruger_1022", "prob": 15 }, - { "group": "nested_shotgun_410", "prob": 10 }, - { "group": "nested_shotgun_s", "prob": 10 }, - { "group": "nested_shotgun_d", "prob": 10 }, - { "group": "nested_sten", "prob": 20 }, - { "group": "nested_sks", "prob": 10 }, - { "group": "nested_aksemi", "prob": 5 } + { "group": "everyday_ar15", "prob": 5 }, + { "group": "everyday_ar_pistol", "prob": 3 }, + { "group": "everyday_mossberg_500", "prob": 5 }, + { "group": "everyday_remington_870", "prob": 5 }, + { "group": "everyday_ruger_1022", "prob": 15 }, + { "group": "everyday_shotgun_410", "prob": 10 }, + { "group": "everyday_shotgun_s", "prob": 10 }, + { "group": "everyday_shotgun_d", "prob": 10 }, + { "group": "everyday_sten", "prob": 20 }, + { "group": "everyday_sks", "prob": 10 }, + { "group": "everyday_aksemi", "prob": 5 } ] } ] diff --git a/data/json/itemgroups/Weapons_Mods_Ammo/nested_ammo.json b/data/json/itemgroups/Weapons_Mods_Ammo/nested_ammo.json index cb4934bde106..41884da0a061 100644 --- a/data/json/itemgroups/Weapons_Mods_Ammo/nested_ammo.json +++ b/data/json/itemgroups/Weapons_Mods_Ammo/nested_ammo.json @@ -354,5 +354,15 @@ { "item": "20x66_inc", "prob": 100, "charges": [ 10, 20 ] }, { "item": "20x66_slug", "prob": 100, "charges": [ 10, 20 ] } ] + }, + { + "id": "on_hand_5x50mm", + "type": "item_group", + "//": "a collection of ammo that would be found with a loaded gun.", + "subtype": "distribution", + "entries": [ + { "item": "5x50dart", "prob": 100, "charges": [ 25, 50 ] }, + { "item": "5x50heavy", "prob": 30, "charges": [ 25, 50 ] } + ] } ] diff --git a/data/json/itemgroups/Weapons_Mods_Ammo/nested_guns.json b/data/json/itemgroups/Weapons_Mods_Ammo/nested_guns.json index bc447700a7ac..17e66c61b121 100644 --- a/data/json/itemgroups/Weapons_Mods_Ammo/nested_guns.json +++ b/data/json/itemgroups/Weapons_Mods_Ammo/nested_guns.json @@ -1932,5 +1932,169 @@ { "item": "saiga410mag_10rd", "prob": 50 }, { "group": "on_hand_410shot" } ] + }, + { + "id": "nested_needlepistol", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "needlepistol", "charges-min": 0, "charges-max": 50 }, + { "item": "5x50_50_mag" }, + { "item": "5x50_50_mag", "prob": 50 }, + { "group": "on_hand_5x50mm" } + ] + }, + { + "id": "nested_rm99_pistol", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm99_pistol", "charges-min": 0, "charges-max": 50 }, + { "item": "8x40_50_mag" }, + { "item": "8x40_50_mag", "prob": 50 }, + { "group": "on_hand_8x40" } + ] + }, + { + "id": "nested_ppsh", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ppsh", "charges-min": 0, "charges-max": 35 }, + { "item": "ppshmag" }, + { "item": "ppshmag", "prob": 50 }, + { "group": "on_hand_762x25" } + ] + }, + { + "id": "nested_skorpion_61", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "skorpion_61", "charges-min": 0, "charges-max": 20 }, + { "item": "skorpion61mag" }, + { "item": "skorpion61mag", "prob": 50 }, + { "group": "on_hand_32" } + ] + }, + { + "id": "nested_skorpion_82", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "skorpion_82", "charges-min": 0, "charges-max": 20 }, + { "item": "skorpion82mag" }, + { "item": "skorpion82mag", "prob": 50 }, + { "group": "on_hand_9x18" } + ] + }, + { + "id": "nested_acr", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "acr", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 }, + { "group": "on_hand_223" } + ] + }, + { + "id": "nested_ar15_retool_300blk", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "ar15_retool_300blk", "charges-min": 0, "charges-max": 30 }, + { "item": "stanag30" }, + { "item": "stanag30", "prob": 50 }, + { "group": "on_hand_300BLK" } + ] + }, + { + "id": "nested_needlegun", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "needlegun", "charges-min": 0, "charges-max": 100 }, + { "item": "5x50_100_mag" }, + { "item": "5x50_100_mag", "prob": 50 }, + { "group": "on_hand_5x50mm" } + ] + }, + { + "id": "nested_rm120c", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ { "item": "rm120c", "charges-min": 0, "charges-max": 5 }, { "group": "on_hand_20x66mm" } ] + }, + { + "id": "nested_rm228", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "rm228", "charges-min": 0, "charges-max": 10 }, + { "item": "20x66_10_mag" }, + { "item": "20x66_10_mag", "prob": 50 }, + { "group": "on_hand_20x66mm" } + ] + }, + { + "id": "nested_an94", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "an94", "charges-min": 0, "charges-max": 30 }, + { "item": "ak74mag" }, + { "item": "ak74mag", "prob": 50 }, + { "group": "on_hand_545x39" } + ] + }, + { + "id": "nested_USAS_12", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "USAS_12", "charges-min": 0, "charges-max": 10 }, + { "item": "USAS10mag" }, + { "item": "USAS10mag", "prob": 50 }, + { "group": "on_hand_shot" } + ] + }, + { + "id": "nested_as50", + "type": "item_group", + "//": "this is a distribution for the gun, reasonable number of backup mags, and some ammo to repack", + "subtype": "collection", + "ammo": 100, + "entries": [ + { "item": "as50", "charges-min": 0, "charges-max": 10 }, + { "item": "as50mag" }, + { "item": "as50mag", "prob": 50 }, + { "group": "on_hand_50" } + ] } ] diff --git a/data/json/itemgroups/military.json b/data/json/itemgroups/military.json index e4895ac8d255..2da020f52bd6 100644 --- a/data/json/itemgroups/military.json +++ b/data/json/itemgroups/military.json @@ -4,8 +4,8 @@ "id": "military_standard_assault_rifles", "subtype": "distribution", "entries": [ - { "item": "m4a1", "prob": 88, "charges": [ 0, 30 ] }, - { "item": "m27iar", "prob": 10, "charges": [ 0, 30 ] }, + { "group": "everyday_m4a1", "prob": 88, "charges": [ 0, 30 ] }, + { "group": "everyday_m27iar", "prob": 10, "charges": [ 0, 30 ] }, { "item": "m16a4", "prob": 2, "charges": [ 0, 30 ] } ] }, @@ -13,29 +13,35 @@ "type": "item_group", "id": "military_standard_shotguns", "subtype": "distribution", - "entries": [ { "item": "m1014", "prob": 60, "charges": [ 0, 8 ] }, { "item": "mossberg_590", "prob": 40, "charges": [ 0, 9 ] } ] + "entries": [ + { "group": "everyday_m1014", "prob": 60, "charges": [ 0, 8 ] }, + { "group": "everyday_mossberg_590", "prob": 40, "charges": [ 0, 9 ] } + ] }, { "type": "item_group", "id": "military_standard_sniper_rifles", "subtype": "distribution", - "entries": [ { "item": "m2010", "prob": 20, "charges": [ 0, 5 ] }, { "item": "m110a1", "prob": 80, "charges": [ 0, 20 ] } ] + "entries": [ + { "group": "everyday_m2010", "prob": 20, "charges": [ 0, 5 ] }, + { "group": "everyday_m110a1", "prob": 80, "charges": [ 0, 20 ] } + ] }, { "type": "item_group", "id": "military_standard_lmgs", "subtype": "distribution", - "entries": [ { "item": "m249", "prob": 100, "charges": [ 0, 100 ] } ] + "entries": [ { "group": "everyday_m249", "prob": 100, "charges": [ 0, 100 ] } ] }, { "type": "item_group", "id": "military_standard_pistols", "subtype": "distribution", "entries": [ - { "item": "m9", "prob": 30, "charges": [ 0, 15 ] }, - { "item": "m17", "prob": 65, "charges": [ 0, 17 ] }, - { "item": "glock_19", "prob": 3, "charges": [ 0, 15 ] }, - { "item": "m1911_MEU", "prob": 2, "charges": [ 0, 7 ] } + { "group": "everyday_m9", "prob": 30, "charges": [ 0, 15 ] }, + { "group": "everyday_m17", "prob": 65, "charges": [ 0, 17 ] }, + { "group": "everyday_glock_19", "prob": 3, "charges": [ 0, 15 ] }, + { "group": "everyday_m1911_MEU", "prob": 2, "charges": [ 0, 7 ] } ] }, { diff --git a/data/json/items/ammo/20x66mm.json b/data/json/items/ammo/20x66mm.json index 297ee0630314..3df875137e00 100644 --- a/data/json/items/ammo/20x66mm.json +++ b/data/json/items/ammo/20x66mm.json @@ -14,31 +14,31 @@ "extend": { "effects": [ "LARGE_BEANBAG", "NOGIB" ] } }, { - "id": "20x66_bootleg_flechette", + "id": "20x66_flechette_reloaded", "copy-from": "20x66_flechette", "type": "AMMO", "name": { "str": "20x66mm flechette, handmade", "str_pl": "20x66mm flechettes, handmade" }, - "description": "Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds. Being caseless rounds, these cannot be disassembled or reloaded.", + "description": "Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being caseless rounds, these cannot be disassembled or reloaded.", "proportional": { "price": 0.7, "damage": { "damage_type": "bullet", "amount": 0.9 }, "dispersion": 1.1 }, "extend": { "effects": [ "RECYCLED" ] }, "delete": { "effects": [ "NEVER_MISFIRES" ], "flags": [ "IRREPLACEABLE_CONSUMABLE" ] } }, { - "id": "20x66_bootleg_shot", + "id": "20x66_shot_reloaded", "copy-from": "20x66_shot", "type": "AMMO", "name": { "str": "20x66mm buckshot, handmade" }, - "description": "Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds. Being caseless rounds, these cannot be disassembled or reloaded.", + "description": "Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being caseless rounds, these cannot be disassembled or reloaded.", "proportional": { "price": 0.7, "damage": { "damage_type": "bullet", "amount": 0.9 }, "dispersion": 1.1 }, "extend": { "effects": [ "RECYCLED" ] }, "delete": { "effects": [ "NEVER_MISFIRES" ], "flags": [ "IRREPLACEABLE_CONSUMABLE" ] } }, { - "id": "20x66_bootleg_slug", + "id": "20x66_slug_reloaded", "copy-from": "20x66_slug", "type": "AMMO", "name": { "str": "20x66mm slug, handmade", "str_pl": "20x66mm slugs, handmade" }, - "description": "Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile rounds. Being caseless rounds, these cannot be disassembled or reloaded.", + "description": "Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. Being caseless rounds, these cannot be disassembled or reloaded.", "proportional": { "price": 0.7, "damage": { "damage_type": "bullet", "amount": 0.9 }, "dispersion": 1.1 }, "extend": { "effects": [ "RECYCLED" ] }, "delete": { "effects": [ "NEVER_MISFIRES" ], "flags": [ "IRREPLACEABLE_CONSUMABLE" ] } @@ -67,7 +67,7 @@ "price_postapoc": 4000, "flags": [ "IRREPLACEABLE_CONSUMABLE" ], "count": 10, - "range": 20, + "range": 28, "damage": { "damage_type": "heat", "amount": 16 }, "dispersion": 200, "recoil": 100, @@ -129,8 +129,8 @@ "count": 20, "stack_size": 20, "ammo_type": "20x66mm", - "range": 12, - "damage": { "damage_type": "bullet", "amount": 60 }, + "range": 20, + "damage": { "damage_type": "bullet", "amount": 100 }, "recoil": 2500, "effects": [ "COOKOFF", "SHOT", "NEVER_MISFIRES" ] }, @@ -152,8 +152,8 @@ "price_postapoc": 4000, "flags": [ "IRREPLACEABLE_CONSUMABLE" ], "//": "Balanced as FMJ", - "damage": { "damage_type": "bullet", "amount": 48, "armor_penetration": 21 }, - "relative": { "range": 12 }, + "damage": { "damage_type": "bullet", "amount": 84, "armor_penetration": 21 }, + "relative": { "range": 20 }, "proportional": { "dispersion": 1.3 }, "delete": { "effects": [ "SHOT" ] } } diff --git a/data/json/items/ammo/410shot.json b/data/json/items/ammo/410shot.json index ffb7db607245..20c86dcf3e8c 100644 --- a/data/json/items/ammo/410shot.json +++ b/data/json/items/ammo/410shot.json @@ -16,8 +16,8 @@ "stack_size": 20, "ammo_type": "410shot", "casing": "410shot_hull", - "range": 12, - "damage": { "damage_type": "bullet", "amount": 30 }, + "range": 20, + "damage": { "damage_type": "bullet", "amount": 53 }, "recoil": 1350, "loudness": 90, "effects": [ "COOKOFF", "SHOT" ] diff --git a/data/json/items/ammo/8x40mm.json b/data/json/items/ammo/8x40mm.json index 8ca62a1bfb3c..de9a47bac7aa 100644 --- a/data/json/items/ammo/8x40mm.json +++ b/data/json/items/ammo/8x40mm.json @@ -1,10 +1,40 @@ [ { - "id": "8mm_bootleg", + "id": "8mm_jhp_reloaded", "copy-from": "8mm_jhp", "type": "AMMO", - "name": { "str": "bootleg 8x40mm JHP" }, - "description": "Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless rounds, these cannot be disassembled or reloaded.", + "name": { "str": "8x40mm JHP, handmade" }, + "description": "Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, these cannot be disassembled or reloaded.", + "proportional": { "price": 0.7, "damage": { "damage_type": "bullet", "amount": 0.9 }, "dispersion": 1.1 }, + "extend": { "effects": [ "RECYCLED" ] }, + "delete": { "effects": [ "NEVER_MISFIRES" ], "flags": [ "IRREPLACEABLE_CONSUMABLE" ] } + }, + { + "id": "8mm_caseless_reloaded", + "copy-from": "8mm_caseless", + "type": "AMMO", + "name": { "str": "8x40mm caseless, handmade" }, + "description": "Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless rounds, these cannot be disassembled or reloaded.", + "proportional": { "price": 0.7, "damage": { "damage_type": "bullet", "amount": 0.9 }, "dispersion": 1.1 }, + "extend": { "effects": [ "RECYCLED" ] }, + "delete": { "effects": [ "NEVER_MISFIRES" ], "flags": [ "IRREPLACEABLE_CONSUMABLE" ] } + }, + { + "id": "8mm_hvp_reloaded", + "copy-from": "8mm_hvp", + "type": "AMMO", + "name": { "str": "8x40mm HVP, handmade" }, + "description": "Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, these cannot be disassembled or reloaded.", + "proportional": { "price": 0.7, "damage": { "damage_type": "bullet", "amount": 0.9 }, "dispersion": 1.1 }, + "extend": { "effects": [ "RECYCLED" ] }, + "delete": { "effects": [ "NEVER_MISFIRES" ], "flags": [ "IRREPLACEABLE_CONSUMABLE" ] } + }, + { + "id": "8mm_inc_reloaded", + "copy-from": "8mm_inc", + "type": "AMMO", + "name": { "str": "8x40mm tracer, handmade" }, + "description": "Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds, these cannot be disassembled or reloaded.", "proportional": { "price": 0.7, "damage": { "damage_type": "bullet", "amount": 0.9 }, "dispersion": 1.1 }, "extend": { "effects": [ "RECYCLED" ] }, "delete": { "effects": [ "NEVER_MISFIRES" ], "flags": [ "IRREPLACEABLE_CONSUMABLE" ] } diff --git a/data/json/items/ammo/flintlock.json b/data/json/items/ammo/flintlock.json index c51ab370e4ad..f68c9b72e099 100644 --- a/data/json/items/ammo/flintlock.json +++ b/data/json/items/ammo/flintlock.json @@ -14,7 +14,7 @@ "count": 30, "stack_size": 10, "ammo_type": "flintlock", - "range": 6, + "range": 12, "//": "Balanced as FMJ", "damage": { "damage_type": "bullet", "amount": 50, "armor_penetration": 22 }, "dispersion": 90, @@ -37,7 +37,7 @@ "count": 30, "stack_size": 10, "ammo_type": "flintlock", - "range": 4, + "range": 8, "damage": { "damage_type": "bullet", "amount": 63 }, "dispersion": 20, "recoil": 1500, diff --git a/data/json/items/ammo/shot.json b/data/json/items/ammo/shot.json index 6282520ffe47..fe30e82e7b9d 100644 --- a/data/json/items/ammo/shot.json +++ b/data/json/items/ammo/shot.json @@ -60,8 +60,8 @@ "stack_size": 20, "ammo_type": "shot", "casing": "shot_hull", - "range": 12, - "damage": { "damage_type": "bullet", "amount": 50 }, + "range": 20, + "damage": { "damage_type": "bullet", "amount": 80, "armor_multiplier": 2.0 }, "recoil": 2500, "loudness": 160, "effects": [ "COOKOFF", "SHOT" ] @@ -96,7 +96,7 @@ "price": 100, "price_postapoc": 400, "range": 0, - "damage": { "damage_type": "bullet", "amount": 20, "armor_multiplier": 2.0 }, + "damage": { "damage_type": "bullet", "amount": 50, "armor_multiplier": 3.0 }, "dispersion": 1000, "loudness": 80, "shape": [ "cone", { "half_angle": 15, "length": 8 } ], @@ -111,7 +111,7 @@ "price": 1000, "price_postapoc": 1600, "flags": [ "IRREPLACEABLE_CONSUMABLE" ], - "damage": { "damage_type": "heat", "amount": 10 }, + "damage": { "damage_type": "heat", "amount": 30 }, "proportional": { "recoil": 0.6, "loudness": 0.8, "dispersion": 1.2 }, "range": 0, "shape": [ "cone", { "half_angle": 15, "length": 8 } ], @@ -128,7 +128,7 @@ "flags": [ "IRREPLACEABLE_CONSUMABLE" ], "count": 10, "//": "Balanced as standard AP.", - "relative": { "damage": { "damage_type": "bullet", "amount": -15, "armor_penetration": 30 } } + "relative": { "damage": { "damage_type": "bullet", "amount": -20, "armor_penetration": 30, "armor_multiplier": -1.0 } } }, { "id": "shot_he", @@ -141,7 +141,7 @@ "price_postapoc": 1600, "flags": [ "IRREPLACEABLE_CONSUMABLE" ], "count": 5, - "damage": { "damage_type": "bullet", "amount": 10, "armor_penetration": 0 }, + "damage": { "damage_type": "bullet", "amount": 30, "armor_penetration": 0 }, "extend": { "effects": [ "EXPLOSIVE" ] } }, { @@ -172,9 +172,9 @@ "price": 400, "price_postapoc": 400, "flags": [ "IRREPLACEABLE_CONSUMABLE" ], - "dispersion": 100, + "dispersion": 80, "//": "Balanced as FMJ", - "relative": { "range": 12, "damage": { "damage_type": "bullet", "amount": -10, "armor_penetration": 18 } }, + "relative": { "range": 12, "damage": { "damage_type": "bullet", "amount": -15, "armor_penetration": 18, "armor_multiplier": -0.5 } }, "proportional": { "recoil": 1.4 }, "delete": { "effects": [ "SHOT" ] } } diff --git a/data/json/items/ammo/shotpaper.json b/data/json/items/ammo/shotpaper.json index 533c9e0ae9ff..c9d1a2ed5889 100644 --- a/data/json/items/ammo/shotpaper.json +++ b/data/json/items/ammo/shotpaper.json @@ -5,7 +5,7 @@ "type": "AMMO", "name": { "str": "birdshot paper cartridge" }, "description": "A paper cartridge containing a premeasured amount of black powder and an equal volume of birdshot. Used mostly for hunting small game or fowl.", - "damage": { "damage_type": "bullet", "amount": 10 }, + "damage": { "damage_type": "bullet", "amount": 40 }, "proportional": { "recoil": 0.6, "loudness": 0.8 }, "extend": { "effects": [ "NOGIB" ] } }, diff --git a/data/json/items/bionics.json b/data/json/items/bionics.json index a930f83177e5..15fefb3cdad3 100644 --- a/data/json/items/bionics.json +++ b/data/json/items/bionics.json @@ -1285,7 +1285,6 @@ "name": { "str": "Linguistic Coprocessor CBM" }, "description": "A microcomputer installed into the left hemisphere of your brain to increase the speed that it processes language. When installed, it provides a passive boost to reading speed.", "price": 100000, - "price_postapoc": 50000, "difficulty": 5 }, { @@ -1294,8 +1293,7 @@ "type": "BIONIC_ITEM", "name": { "str": "Dopamine Stimulators CBM" }, "description": "A set of tiny bionic nerve stimulators that install into the reward center of your brain. When run with bionic power, it periodically releases a hit of dopamine and other reward chemicals, inducing a state of euphoria and suppressing fear.", - "price": 1000000, - "price_postapoc": 100000, + "price": 100000, "difficulty": 8 }, { @@ -1312,7 +1310,15 @@ "copy-from": "bionic_general", "type": "BIONIC_ITEM", "name": { "str": "Perpetual Generator CBM" }, - "description": "Installed within you is a perpetual generator powered by nonsensoleum. When activated it's power gen doubles. If you are seeing this, you'd better be debugging.", + "description": "Installed within you is a perpetual generator powered by nonsensoleum. When activated its power gen doubles. If you are seeing this, you'd better be debugging.", + "price": 0 + }, + { + "id": "debug_bio_fuel_cell", + "copy-from": "bionic_general", + "type": "BIONIC_ITEM", + "name": { "str": "Debug Fuel Cell CBM" }, + "description": "The power of the sun, in the palm of my hand! Installed within you is a perpetual generator powered by nonsensoleum. When activated its power gen doubles. If you are seeing this, you'd better be debugging.", "price": 0 } ] diff --git a/data/json/items/comestibles/egg.json b/data/json/items/comestibles/egg.json index aba40e4b8114..1b8ac799aa4b 100644 --- a/data/json/items/comestibles/egg.json +++ b/data/json/items/comestibles/egg.json @@ -305,5 +305,89 @@ "price_postapoc": 75, "material": "egg", "fun": 2 + }, + { + "type": "COMESTIBLE", + "id": "salsify_omelette", + "name": { "str_sp": "salsify omelette" }, + "color": "yellow", + "spoils_in": "2 days", + "comestible_type": "FOOD", + "symbol": "%", + "description": "A salsify omelette.", + "quench": 4, + "healthy": 1, + "calories": 349, + "vitamins": [ [ "vitA", 9 ], [ "vitC", 18 ], [ "calcium", 11 ], [ "iron", 9 ], [ "vitB", 21 ] ], + "price": 490, + "price_postapoc": 150, + "material": [ "egg", "veggy" ], + "volume": "125 ml", + "charges": 2, + "flags": [ "EATEN_HOT", "NUTRIENT_OVERRIDE" ], + "fun": 3 + }, + { + "type": "COMESTIBLE", + "id": "wild_veggy_omelette", + "name": { "str_sp": "wild veggetable omelette" }, + "color": "yellow", + "spoils_in": "2 days", + "symbol": "%", + "description": "An omelette made with wild vegetables.", + "quench": 4, + "comestible_type": "FOOD", + "healthy": 1, + "calories": 194, + "vitamins": [ [ "vitA", 9 ], [ "vitC", 36 ], [ "calcium", 7 ], [ "iron", 8 ], [ "vitB", 21 ] ], + "price": 1190, + "price_postapoc": 200, + "material": [ "egg", "veggy" ], + "volume": "125 ml", + "charges": 2, + "flags": [ "EATEN_HOT", "NUTRIENT_OVERRIDE" ], + "fun": 3 + }, + { + "type": "COMESTIBLE", + "id": "mushroom_omelette", + "name": { "str_sp": "mushroom omelette" }, + "color": "yellow", + "spoils_in": "2 days", + "symbol": "%", + "description": "An omelette made with mushrooms.", + "quench": 4, + "healthy": 1, + "comestible_type": "FOOD", + "calories": 175, + "vitamins": [ [ "vitA", 9 ], [ "vitC", 4 ], [ "calcium", 3 ], [ "iron", 11 ], [ "vitB", 21 ] ], + "price": 400, + "price_postapoc": 100, + "material": [ "egg", "veggy" ], + "volume": "125 ml", + "charges": 2, + "flags": [ "EATEN_HOT", "NUTRIENT_OVERRIDE" ], + "fun": 3 + }, + { + "type": "COMESTIBLE", + "id": "spanish_omelette", + "name": { "str_sp": "spanish omelette" }, + "color": "yellow", + "spoils_in": "2 days", + "symbol": "%", + "description": "A spanish omelette.", + "quench": 4, + "comestible_type": "FOOD", + "healthy": 1, + "calories": 322, + "vitamins": [ [ "vitA", 10 ], [ "vitC", 9 ], [ "calcium", 13 ], [ "iron", 12 ], [ "vitB", 21 ] ], + "price": 400, + "price_postapoc": 100, + "material": "egg", + "volume": "125 ml", + "charges": 2, + "flags": [ "EATEN_HOT", "NUTRIENT_OVERRIDE" ], + "fun": 3 } ] diff --git a/data/json/items/comestibles/meat_dishes.json b/data/json/items/comestibles/meat_dishes.json index 7091d286a58d..dedfeaf32909 100644 --- a/data/json/items/comestibles/meat_dishes.json +++ b/data/json/items/comestibles/meat_dishes.json @@ -467,7 +467,7 @@ "volume": "500 ml", "charges": 6, "flags": [ "EATEN_HOT" ], - "fun": -8, + "fun": -2, "vitamins": [ [ "iron", 3 ] ] }, { diff --git a/data/json/items/gun/monster_gun.json b/data/json/items/gun/monster_gun.json index 67ca08407369..8772f71aa5fc 100644 --- a/data/json/items/gun/monster_gun.json +++ b/data/json/items/gun/monster_gun.json @@ -78,8 +78,8 @@ "weight": "3402 g", "volume": "2450 ml", "bashing": 3, - "dispersion": 3250, - "range": 65, + "dispersion": 6500, + "range": 30, "durability": 9 }, { diff --git a/data/json/items/magazine/223.json b/data/json/items/magazine/223.json index 11ac7ac14b1a..058ce68094c7 100644 --- a/data/json/items/magazine/223.json +++ b/data/json/items/magazine/223.json @@ -128,6 +128,7 @@ "weight": "88 g", "volume": "50 ml", "price": 4000, + "price_postapoc": 50, "material": "steel", "symbol": "#", "color": "light_gray", @@ -145,6 +146,7 @@ "weight": "91 g", "volume": "350 ml", "price": 4000, + "price_postapoc": 150, "material": "steel", "symbol": "#", "color": "light_gray", @@ -180,6 +182,7 @@ "weight": "181 g", "volume": "600 ml", "price": 8500, + "price_postapoc": 400, "material": [ "plastic", "steel" ], "symbol": "#", "color": "light_gray", @@ -218,6 +221,7 @@ "weight": "181 g", "volume": "800 ml", "price": 12000, + "price_postapoc": 800, "material": "aluminum", "symbol": "#", "color": "light_gray", @@ -235,6 +239,7 @@ "weight": "581 g", "volume": "1050 ml", "price": 9250, + "price_postapoc": 800, "to_hit": -2, "bashing": 4, "material": [ "steel", "plastic" ], @@ -255,6 +260,7 @@ "weight": "567 g", "volume": "1500 ml", "price": 9500, + "price_postapoc": 1400, "to_hit": -2, "bashing": 4, "material": [ "plastic", "steel" ], @@ -275,6 +281,7 @@ "weight": "272 g", "volume": "1 L", "price": 15000, + "price_postapoc": 1800, "material": "aluminum", "symbol": "#", "color": "light_gray", @@ -292,6 +299,7 @@ "weight": "998 g", "volume": "1200 ml", "price": 14000, + "price_postapoc": 1800, "material": [ "plastic", "steel" ], "symbol": "#", "color": "light_gray", @@ -310,6 +318,7 @@ "weight": "2220 g", "volume": "1700 ml", "price": 18000, + "price_postapoc": 2500, "material": [ "plastic", "steel" ], "symbol": "#", "color": "light_gray", diff --git a/data/json/monsterdrops/zombie_cop.json b/data/json/monsterdrops/zombie_cop.json index b6ffe66e4b5f..3286612658fa 100644 --- a/data/json/monsterdrops/zombie_cop.json +++ b/data/json/monsterdrops/zombie_cop.json @@ -79,7 +79,7 @@ { "id": "cop_weapons", "type": "item_group", - "items": [ { "group": "cop_melee", "prob": 60 }, { "group": "guns_cop", "prob": 40 } ] + "items": [ { "group": "cop_melee", "prob": 60 }, { "group": "carried_guns_cop", "prob": 40 } ] }, { "id": "mon_zombie_swat_death_drops", @@ -193,6 +193,6 @@ "id": "swat_weapons", "type": "item_group", "subtype": "collection", - "entries": [ { "group": "cop_melee", "prob": 25 }, { "group": "guns_swat", "prob": 75 } ] + "entries": [ { "group": "cop_melee", "prob": 25 }, { "group": "carried_guns_swat", "prob": 75 } ] } ] diff --git a/data/json/monsterdrops/zombie_default.json b/data/json/monsterdrops/zombie_default.json index 85a06228b25b..676d8e9418c2 100644 --- a/data/json/monsterdrops/zombie_default.json +++ b/data/json/monsterdrops/zombie_default.json @@ -223,8 +223,8 @@ [ "default_zombie_items_pockets", 20 ], [ "ammo_pistol_common", 2 ], [ "ammo_shotgun_common", 1 ], - [ "guns_pistol_common", 2 ], - [ "guns_shotgun_common", 1 ], + [ "carried_guns_pistol_common", 2 ], + [ "carried_guns_shotgun_common", 1 ], [ "postman_gear", 5 ], [ "hardware_plumbing", 5 ] ] diff --git a/data/json/monsterdrops/zombie_soldier.json b/data/json/monsterdrops/zombie_soldier.json index fea68524f8ae..004e9fb9a7bf 100644 --- a/data/json/monsterdrops/zombie_soldier.json +++ b/data/json/monsterdrops/zombie_soldier.json @@ -14,7 +14,8 @@ }, { "group": "infantry_common_gear" }, { "group": "military_standard_guns", "prob": 10, "damage": [ 0, 2 ], "dirt": [ 1500, 7050 ] }, - { "item": "holster", "contents-group": "military_standard_pistols", "prob": 30 }, + { "item": "holster" }, + { "group": "military_standard_pistols", "prob": 30 }, { "group": "military_standard_grenades", "count": [ 1, 3 ], "prob": 20 }, { "group": "military_patrol_food" }, { "distribution": [ { "group": "infantry_officer_gear" }, { "group": "infantry_medical_gear" } ], "prob": 25 }, @@ -43,7 +44,8 @@ }, { "group": "infantry_common_gear" }, { "group": "military_standard_guns", "prob": 10, "damage": [ 0, 2 ], "dirt": [ 1500, 7050 ] }, - { "item": "holster", "contents-group": "military_standard_pistols", "prob": 30 }, + { "item": "holster" }, + { "group": "military_standard_pistols", "prob": 30 }, { "group": "military_standard_grenades", "count": [ 1, 3 ], "prob": 20 }, { "group": "military_patrol_food" }, { diff --git a/data/json/monsters/reptile_amphibian.json b/data/json/monsters/reptile_amphibian.json index 7a0e324e5884..aa6d9e66ea6c 100644 --- a/data/json/monsters/reptile_amphibian.json +++ b/data/json/monsters/reptile_amphibian.json @@ -110,7 +110,7 @@ "fear_triggers": [ "PLAYER_CLOSE" ], "placate_triggers": [ "PLAYER_WEAK" ], "death_function": [ "NORMAL" ], - "flags": [ "SEES", "HEARS", "SMELLS", "BADVENOM", "HARDTOSHOOT", "SWIMS" ] + "flags": [ "SEES", "HEARS", "SMELLS", "BADVENOM", "HARDTOSHOOT", "SWIMS", "ANIMAL" ] }, { "id": "mon_rattlesnake_giant", diff --git a/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json b/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json index 3ec807bd27bb..74db2b522a3d 100644 --- a/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +++ b/data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json @@ -226,10 +226,46 @@ }, "responses": [ { - "text": "Wait! What??", + "text": "I was sent here by the traders at the refugee center. They told me to deliver this hard drive to you.", + "condition": { + "and": [ + { "not": { "u_has_var": "completed_robofac_intercom_1", "type": "dialogue", "context": "intercom", "value": "yes" } }, + { + "not": { "u_has_var": "completed_free_merchants_hub_delivery_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, + { "u_has_mission": "MISSION_FREE_MERCHANTS_HUB_DELIVERY_1" } + ] + }, + "topic": "TALK_ROBOFAC_INTERCOM_FREE_MERCHANT_DELIVERY_1" + }, + { + "text": "The traders also mentioned you were looking for help.", "condition": { "and": [ { "not": { "u_has_var": "completed_robofac_intercom_1", "type": "dialogue", "context": "intercom", "value": "yes" } }, + { + "u_has_var": "completed_free_merchants_hub_delivery_1", + "type": "dialogue", + "context": "intercom", + "value": "yes" + } + ] + }, + "trial": { "type": "LIE", "difficulty": 1 }, + "success": { "topic": "MISSION_ROBOFAC_INTERCOM_1_INTRODUCTION" }, + "failure": { "topic": "MISSION_ROBOFAC_INTERCOM_1_INTRODUCTION" } + }, + { + "text": "Wait! What??", + "condition": { + "and": [ + { + "not": { "u_has_var": "completed_free_merchants_hub_delivery_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, + { "not": { "u_has_mission": "MISSION_FREE_MERCHANTS_HUB_DELIVERY_1" } }, + { + "not": { "u_has_var": "completed_robofac_intercom_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, { "not": { "u_has_mission": "MISSION_ROBOFAC_INTERCOM_1" } } ] }, @@ -239,7 +275,13 @@ "text": "You do realize that the front door is just open?", "condition": { "and": [ - { "not": { "u_has_var": "completed_robofac_intercom_1", "type": "dialogue", "context": "intercom", "value": "yes" } }, + { + "not": { "u_has_var": "completed_free_merchants_hub_delivery_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, + { "not": { "u_has_mission": "MISSION_FREE_MERCHANTS_HUB_DELIVERY_1" } }, + { + "not": { "u_has_var": "completed_robofac_intercom_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, { "not": { "u_has_mission": "MISSION_ROBOFAC_INTERCOM_1" } } ] }, @@ -255,7 +297,13 @@ "text": "It's the apocalypse out here! Please let me in!", "condition": { "and": [ - { "not": { "u_has_var": "completed_robofac_intercom_1", "type": "dialogue", "context": "intercom", "value": "yes" } }, + { + "not": { "u_has_var": "completed_free_merchants_hub_delivery_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, + { "not": { "u_has_mission": "MISSION_FREE_MERCHANTS_HUB_DELIVERY_1" } }, + { + "not": { "u_has_var": "completed_robofac_intercom_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, { "not": { "u_has_mission": "MISSION_ROBOFAC_INTERCOM_1" } } ] }, @@ -265,7 +313,13 @@ "text": "I was just looking for valuables, maybe I can trade with you instead?", "condition": { "and": [ - { "not": { "npc_has_var": "npc_failed_intercom_trade", "type": "dialogue", "context": "intercom", "value": "yes" } }, + { + "not": { "u_has_var": "completed_free_merchants_hub_delivery_1", "type": "dialogue", "context": "intercom", "value": "yes" } + }, + { "not": { "u_has_mission": "MISSION_FREE_MERCHANTS_HUB_DELIVERY_1" } }, + { + "not": { "npc_has_var": "npc_failed_intercom_trade", "type": "dialogue", "context": "intercom", "value": "yes" } + }, { "not": { "npc_has_var": "npc_intercom_trade", "type": "dialogue", "context": "intercom", "value": "yes" } } @@ -307,6 +361,28 @@ } ] }, + { + "id": "TALK_ROBOFAC_INTERCOM_FREE_MERCHANT_DELIVERY_1", + "type": "talk_topic", + "dynamic_line": "Understood. Please drop the drive on the box embedded beneath the intercom. You are welcome to leave afterwards.", + "responses": [ + { + "text": "[Do as the Intercom Says]", + "condition": { "u_has_items": { "item": "fema_data", "count": 1 } }, + "effect": [ + { "u_sell_item": "fema_data", "count": 1 }, + { + "u_add_var": "completed_free_merchants_hub_delivery_1", + "type": "dialogue", + "context": "intercom", + "value": "yes" + } + ], + "topic": "TALK_DONE" + }, + { "text": "Didn't bring the hard drive now, let me return with it.", "topic": "TALK_DONE" } + ] + }, { "id": "TALK_ROBOFAC_INTERCOM_NO_TRADE", "type": "talk_topic", diff --git a/data/json/obsoletion/migration.json b/data/json/obsoletion/migration.json index aae147246c5e..1d37113786da 100644 --- a/data/json/obsoletion/migration.json +++ b/data/json/obsoletion/migration.json @@ -69,10 +69,30 @@ "type": "MIGRATION", "replace": "40x46mm_m651" }, + { + "id": "8mm_bootleg", + "type": "MIGRATION", + "replace": "8mm_jhp_reloaded" + }, { "id": "8mm_bootleg_jsp", "type": "MIGRATION", - "replace": "8mm_bootleg" + "replace": "8mm_jhp_reloaded" + }, + { + "id": "20x66_bootleg_shot", + "type": "MIGRATION", + "replace": "20x66_shot_reloaded" + }, + { + "id": "20x66_bootleg_flechette", + "type": "MIGRATION", + "replace": "20x66_flechette_reloaded" + }, + { + "id": "20x66_bootleg_slug", + "type": "MIGRATION", + "replace": "20x66_slug_reloaded" }, { "id": "adv_UPS_on", diff --git a/data/json/recipes/ammo/rifle.json b/data/json/recipes/ammo/rifle.json index dc0713e00bcb..64b2d43cdf68 100644 --- a/data/json/recipes/ammo/rifle.json +++ b/data/json/recipes/ammo/rifle.json @@ -395,6 +395,135 @@ "using": [ [ "bullet_forming", 15 ], [ "ammo_bullet", 8 ] ], "components": [ [ [ "4570_casing", 1 ] ], [ [ "lgrifle_primer", 1 ] ], [ [ "chem_black_powder", 12 ] ] ] }, + { + "type": "recipe", + "result": "8mm_jhp_reloaded", + "category": "CC_AMMO", + "subcategory": "CSC_AMMO_RIFLE", + "skill_used": "fabrication", + "skills_required": [ "cooking", 2 ], + "difficulty": 8, + "time": 35000, + "batch_time_factors": [ 60, 5 ], + "book_learn": [ [ "recipe_caseless", 5 ] ], + "charges": 40, + "qualities": [ { "id": "CHEM", "level": 2 } ], + "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], + "components": [ + [ [ "adhesive", 1, "LIST" ] ], + [ [ "plastic_chunk", 5 ] ], + [ [ "gunpowder", 280 ] ], + [ [ "oxy_powder", 80 ] ], + [ [ "lead", 80 ] ], + [ + [ "gold_small", 4 ], + [ "silver_small", 4 ], + [ "tin", 4 ], + [ "bismuth", 4 ], + [ "solder_wire", 4 ], + [ "platinum_small", 4 ] + ], + [ [ "copper", 40 ] ], + [ [ "smrifle_primer", 1 ], [ "lgpistol_primer", 1 ] ] + ] + }, + { + "type": "recipe", + "result": "8mm_caseless_reloaded", + "category": "CC_AMMO", + "subcategory": "CSC_AMMO_RIFLE", + "skill_used": "fabrication", + "skills_required": [ "cooking", 2 ], + "difficulty": 9, + "time": 45000, + "batch_time_factors": [ 60, 5 ], + "book_learn": [ [ "recipe_caseless", 5 ] ], + "charges": 40, + "qualities": [ { "id": "CHEM", "level": 2 } ], + "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], + "components": [ + [ [ "adhesive", 1, "LIST" ] ], + [ [ "plastic_chunk", 5 ] ], + [ [ "gunpowder", 320 ] ], + [ [ "oxy_powder", 80 ] ], + [ [ "lead", 120 ] ], + [ + [ "gold_small", 4 ], + [ "silver_small", 4 ], + [ "tin", 4 ], + [ "bismuth", 4 ], + [ "solder_wire", 4 ], + [ "platinum_small", 4 ] + ], + [ [ "copper", 80 ] ], + [ [ "smrifle_primer", 1 ], [ "lgpistol_primer", 1 ] ] + ] + }, + { + "type": "recipe", + "result": "8mm_hvp_reloaded", + "category": "CC_AMMO", + "subcategory": "CSC_AMMO_RIFLE", + "skill_used": "fabrication", + "skills_required": [ "cooking", 2 ], + "difficulty": 9, + "time": 55000, + "batch_time_factors": [ 60, 5 ], + "book_learn": [ [ "recipe_caseless", 5 ] ], + "charges": 40, + "qualities": [ { "id": "CHEM", "level": 2 } ], + "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], + "components": [ + [ [ "adhesive", 1, "LIST" ] ], + [ [ "plastic_chunk", 5 ] ], + [ [ "gunpowder", 400 ] ], + [ [ "oxy_powder", 120 ] ], + [ [ "lead", 80 ] ], + [ + [ "gold_small", 40 ], + [ "silver_small", 40 ], + [ "tin", 40 ], + [ "bismuth", 40 ], + [ "solder_wire", 40 ], + [ "platinum_small", 40 ] + ], + [ [ "copper", 80 ] ], + [ [ "smrifle_primer", 1 ], [ "lgpistol_primer", 1 ] ] + ] + }, + { + "type": "recipe", + "result": "8mm_inc_reloaded", + "category": "CC_AMMO", + "subcategory": "CSC_AMMO_RIFLE", + "skill_used": "fabrication", + "skills_required": [ "cooking", 2 ], + "difficulty": 9, + "time": 55000, + "batch_time_factors": [ 60, 5 ], + "book_learn": [ [ "recipe_caseless", 5 ] ], + "charges": 40, + "qualities": [ { "id": "CHEM", "level": 2 } ], + "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], + "components": [ + [ [ "adhesive", 1, "LIST" ] ], + [ [ "plastic_chunk", 5 ] ], + [ [ "gunpowder", 320 ] ], + [ [ "oxy_powder", 160 ] ], + [ [ "incendiary", 80 ] ], + [ [ "lead", 80 ] ], + [ + [ "gold_small", 4 ], + [ "silver_small", 4 ], + [ "tin", 4 ], + [ "bismuth", 4 ], + [ "solder_wire", 4 ], + [ "platinum_small", 4 ] + ], + [ [ "copper", 40 ] ], + [ [ "smrifle_primer", 1 ], [ "lgpistol_primer", 1 ] ] + ] + }, { "result": "5x50dart", "type": "recipe", @@ -406,15 +535,15 @@ "time": "2 m", "batch_time_factors": [ 60, 5 ], "book_learn": [ [ "recipe_caseless", 4 ] ], - "charges": 1, - "using": [ [ "bullet_forming", 2 ], [ "ammo_bullet", 2 ] ], + "charges": 8, + "using": [ [ "bullet_forming", 16 ], [ "ammo_bullet", 16 ] ], "tools": [ [ [ "mold_plastic", -1 ] ] ], "components": [ - [ [ "5x50_hull", 1 ] ], + [ [ "5x50_hull", 8 ] ], [ [ "plastic_chunk", 1 ] ], - [ [ "smrifle_primer", 1 ] ], - [ [ "gunpowder", 3 ] ], - [ [ "combatnail", 1 ] ] + [ [ "smrifle_primer", 8 ] ], + [ [ "gunpowder", 24 ] ], + [ [ "combatnail", 8 ] ] ] }, { @@ -428,15 +557,15 @@ "time": "2 m", "batch_time_factors": [ 60, 5 ], "book_learn": [ [ "recipe_caseless", 4 ] ], - "charges": 1, - "using": [ [ "bullet_forming", 2 ], [ "ammo_bullet", 3 ] ], + "charges": 8, + "using": [ [ "bullet_forming", 16 ], [ "ammo_bullet", 24 ] ], "tools": [ [ [ "mold_plastic", -1 ] ] ], "components": [ - [ [ "5x50_hull", 1 ] ], + [ [ "5x50_hull", 8 ] ], [ [ "plastic_chunk", 1 ] ], - [ [ "smrifle_primer", 1 ] ], - [ [ "gunpowder", 4 ] ], - [ [ "scrap", 1 ] ] + [ [ "smrifle_primer", 8 ] ], + [ [ "gunpowder", 32 ] ], + [ [ "scrap", 8 ] ] ] }, { diff --git a/data/json/recipes/ammo/shot.json b/data/json/recipes/ammo/shot.json index 27b7bb178320..6221603cd0d9 100644 --- a/data/json/recipes/ammo/shot.json +++ b/data/json/recipes/ammo/shot.json @@ -642,5 +642,78 @@ "using": [ [ "ammo_bullet", 8 ] ], "qualities": [ { "id": "CUT", "level": 1 } ], "components": [ [ [ "chem_black_powder", 5 ] ], [ [ "shotgun_primer", 1 ] ], [ [ "paper", 1 ], [ "aluminum_foil", 1 ] ] ] + }, + { + "type": "recipe", + "result": "20x66_shot_reloaded", + "category": "CC_AMMO", + "subcategory": "CSC_AMMO_SHOT", + "skill_used": "fabrication", + "skills_required": [ "cooking", 2 ], + "difficulty": 8, + "time": 45000, + "batch_time_factors": [ 60, 5 ], + "book_learn": [ [ "recipe_caseless", 5 ] ], + "qualities": [ { "id": "CHEM", "level": 2 } ], + "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], + "components": [ + [ [ "adhesive", 1, "LIST" ] ], + [ [ "plastic_chunk", 4 ] ], + [ [ "oxy_powder", 60 ] ], + [ [ "gunpowder", 120 ] ], + [ [ "lead", 160 ] ], + [ [ "gold_small", 5 ], [ "silver_small", 5 ], [ "tin", 5 ], [ "bismuth", 5 ], [ "solder_wire", 5 ] ] + ] + }, + { + "type": "recipe", + "result": "20x66_flechette_reloaded", + "category": "CC_AMMO", + "subcategory": "CSC_AMMO_SHOT", + "skill_used": "fabrication", + "skills_required": [ "cooking", 2 ], + "difficulty": 8, + "time": 45000, + "batch_time_factors": [ 60, 5 ], + "book_learn": [ [ "recipe_caseless", 5 ] ], + "qualities": [ { "id": "CHEM", "level": 2 } ], + "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "boltcutters", -1 ], [ "toolset", -1 ] ], [ [ "press", -1 ] ] ], + "components": [ + [ [ "adhesive", 1, "LIST" ] ], + [ [ "plastic_chunk", 4 ] ], + [ [ "oxy_powder", 60 ] ], + [ [ "gunpowder", 120 ] ], + [ + [ "lead", 10 ], + [ "gold_small", 10 ], + [ "silver_small", 10 ], + [ "tin", 10 ], + [ "bismuth", 10 ], + [ "solder_wire", 10 ] + ], + [ [ "nail", 240 ], [ "combatnail", 240 ] ] + ] + }, + { + "type": "recipe", + "result": "20x66_slug_reloaded", + "category": "CC_AMMO", + "subcategory": "CSC_AMMO_SHOT", + "skill_used": "fabrication", + "skills_required": [ "cooking", 2 ], + "difficulty": 8, + "time": 45000, + "batch_time_factors": [ 60, 5 ], + "book_learn": [ [ "recipe_caseless", 5 ] ], + "qualities": [ { "id": "CHEM", "level": 2 } ], + "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], + "components": [ + [ [ "adhesive", 1, "LIST" ] ], + [ [ "plastic_chunk", 4 ] ], + [ [ "oxy_powder", 80 ] ], + [ [ "gunpowder", 160 ] ], + [ [ "lead", 240 ] ], + [ [ "gold_small", 8 ], [ "silver_small", 8 ], [ "tin", 8 ], [ "bismuth", 8 ], [ "solder_wire", 8 ] ] + ] } ] diff --git a/data/json/recipes/chem/chemicals.json b/data/json/recipes/chem/chemicals.json index af2805136135..a7c78761cf74 100644 --- a/data/json/recipes/chem/chemicals.json +++ b/data/json/recipes/chem/chemicals.json @@ -389,6 +389,22 @@ "tools": [ [ [ "surface_heat", 10, "LIST" ] ] ], "components": [ [ [ "chem_hydrogen_peroxide_conc", 1 ] ], [ [ "chem_sulphur", 375 ] ] ] }, + { + "type": "recipe", + "result": "chem_sulphuric_acid", + "id_suffix": "from SO3", + "category": "CC_CHEM", + "subcategory": "CSC_CHEM_CHEMICALS", + "skill_used": "cooking", + "difficulty": 8, + "time": "60 m", + "book_learn": [ [ "textbook_chemistry", 4 ], [ "adv_chemistry", 5 ] ], + "batch_time_factors": [ 80, 5 ], + "qualities": [ { "id": "BOIL", "level": 2 }, { "id": "CHEM", "level": 2 } ], + "using": [ [ "forging_standard", 50 ] ], + "tools": [ [ [ "surface_heat", 25, "LIST" ] ], [ [ "platinum_grille", -1 ] ] ], + "components": [ [ [ "water_clean", 1 ] ], [ [ "chem_sulphur", 470 ] ] ] + }, { "type": "recipe", "result": "chem_nitric_acid", diff --git a/data/json/recipes/food/other.json b/data/json/recipes/food/other.json index 7880d3dd353d..dddefcaa2579 100644 --- a/data/json/recipes/food/other.json +++ b/data/json/recipes/food/other.json @@ -2064,5 +2064,125 @@ [ [ "rock_quern", -1 ], [ "clay_quern", -1 ], [ "mortar_pestle", -1 ], [ "food_processor", 10 ] ] ], "components": [ [ [ "stomach_large", 1 ], [ "stomach", 2 ] ] ] + }, + { + "type": "recipe", + "result": "salsify_omelette", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "6 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ [ [ "eggs_small", 2, "LIST" ] ], [ [ "salsify_raw", 1 ] ] ] + }, + { + "type": "recipe", + "result": "salsify_omelette", + "id_suffix": "from_powder", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "6 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ [ [ "eggs_small_dry", 2, "LIST" ] ], [ [ "water", 2 ], [ "water_clean", 2 ] ], [ [ "salsify_raw", 1 ] ] ] + }, + { + "type": "recipe", + "result": "wild_veggy_omelette", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "6 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ [ [ "eggs_small", 2, "LIST" ] ], [ [ "veggy_wild", 1 ] ] ] + }, + { + "type": "recipe", + "result": "wild_veggy_omelette", + "id_suffix": "from_powder", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "6 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ [ [ "eggs_small_dry", 2, "LIST" ] ], [ [ "water", 2 ], [ "water_clean", 2 ] ], [ [ "veggy_wild", 1 ] ] ] + }, + { + "type": "recipe", + "result": "mushroom_omelette", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "6 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ [ [ "eggs_small", 2, "LIST" ] ], [ [ "dry_mushroom", 1 ], [ "mushroom", 1 ] ] ] + }, + { + "type": "recipe", + "result": "mushroom_omelette", + "id_suffix": "from_powder", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "6 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ + [ [ "eggs_small_dry", 2, "LIST" ] ], + [ [ "water", 2 ], [ "water_clean", 2 ] ], + [ [ "dry_mushroom", 1 ], [ "mushroom", 1 ] ] + ] + }, + { + "type": "recipe", + "result": "spanish_omelette", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "6 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ [ [ "eggs_small", 2, "LIST" ] ], [ [ "potato", 1 ], [ "irradiated_potato", 1 ] ] ] + }, + { + "type": "recipe", + "result": "spanish_omelette", + "id_suffix": "from_powder", + "category": "CC_FOOD", + "subcategory": "CSC_FOOD_OTHER", + "skill_used": "cooking", + "difficulty": 1, + "time": "13 m", + "autolearn": true, + "batch_time_factors": [ 80, 1 ], + "qualities": [ { "id": "COOK", "level": 2 } ], + "tools": [ [ [ "surface_heat", 2, "LIST" ] ] ], + "components": [ [ [ "eggs_small_dry", 2, "LIST" ] ], [ [ "water", 2 ], [ "water_clean", 2 ] ], [ [ "potato", 1 ] ] ] } ] diff --git a/data/json/recipes/other/other.json b/data/json/recipes/other/other.json index 02a658b1558b..3d6cea1ceceb 100644 --- a/data/json/recipes/other/other.json +++ b/data/json/recipes/other/other.json @@ -49,6 +49,18 @@ "using": [ [ "sewing_standard", 12 ] ], "components": [ [ [ "rag", 4 ] ], [ [ "cotton_ball", 8 ] ] ] }, + { + "type": "recipe", + "result": "bodypillow", + "category": "CC_OTHER", + "subcategory": "CSC_OTHER_OTHER", + "skill_used": "tailor", + "time": "20 m", + "difficulty": 2, + "autolearn": true, + "using": [ [ "sewing_standard", 12 ], [ "drawing_tool", 20 ] ], + "components": [ [ [ "sheet", 1 ] ], [ [ "cotton_ball", 20 ] ] ] + }, { "type": "recipe", "result": "shelter_kit", diff --git a/data/json/recipes/other/tools.json b/data/json/recipes/other/tools.json index 27b613400c78..ea953ab965e9 100644 --- a/data/json/recipes/other/tools.json +++ b/data/json/recipes/other/tools.json @@ -1004,6 +1004,23 @@ "autolearn": true, "using": [ [ "blacksmithing_standard", 4 ], [ "steel_standard", 1 ] ] }, + { + "type": "recipe", + "result": "pressure_cooker", + "category": "CC_OTHER", + "subcategory": "CSC_OTHER_TOOLS", + "skill_used": "fabrication", + "difficulty": 6, + "time": "2 h", + "autolearn": true, + "using": [ [ "blacksmithing_intermediate", 4 ], [ "steel_standard", 4 ] ], + "components": [ + [ [ "pot_canning", 1 ], [ "stock_pot", 1 ], [ "pot", 1 ], [ "steel_lump", 1 ], [ "steel_chunk", 4 ], [ "scrap", 20 ] ], + [ [ "thermometer", 1 ] ], + [ [ "barometer", 1 ] ], + [ [ "chunk_rubber", 5 ] ] + ] + }, { "type": "recipe", "result": "teapot", diff --git a/data/json/requirements/toolsets.json b/data/json/requirements/toolsets.json index 07063a68b6ed..f14720b7e165 100644 --- a/data/json/requirements/toolsets.json +++ b/data/json/requirements/toolsets.json @@ -90,6 +90,12 @@ "tools": [ [ [ "soldering_iron", 1 ], [ "toolset", 1 ] ] ], "components": [ [ [ "solder_wire", 1 ] ] ] }, + { + "id": "drawing_tool", + "type": "requirement", + "//": "Things suitable for drawing or writing something on paper, cardboard, cloth or similar materials.", + "tools": [ [ [ "permanent_marker", 1 ], [ "survival_marker", 1 ] ] ] + }, { "id": "coding_standard", "type": "requirement", diff --git a/data/json/uncraft/generic.json b/data/json/uncraft/generic.json index 23c0059c9827..b93c845908c1 100644 --- a/data/json/uncraft/generic.json +++ b/data/json/uncraft/generic.json @@ -1886,6 +1886,30 @@ "time": "2 m", "components": [ [ [ "glass_shard", 18 ] ] ] }, + { + "result": "bottle_glass", + "type": "uncraft", + "time": "30 s", + "components": [ [ [ "glass_shard", 2 ] ] ] + }, + { + "result": "jar_glass", + "type": "uncraft", + "time": "30 s", + "components": [ [ [ "glass_shard", 2 ] ] ] + }, + { + "result": "flask_glass", + "type": "uncraft", + "time": "30 s", + "components": [ [ [ "glass_shard", 1 ] ] ] + }, + { + "result": "jar_3l_glass", + "type": "uncraft", + "time": "30 s", + "components": [ [ [ "glass_shard", 3 ] ] ] + }, { "result": "game_watch", "type": "uncraft", diff --git a/data/json/vehicleparts/vehicle_parts.json b/data/json/vehicleparts/vehicle_parts.json index 35ce65c786dd..c9962956db69 100644 --- a/data/json/vehicleparts/vehicle_parts.json +++ b/data/json/vehicleparts/vehicle_parts.json @@ -2597,7 +2597,6 @@ "item": "omnicamera", "//": "Cameras without a DVR can run on under 10W", "epower": -10, - "location": "on_roof", "requirements": { "install": { "skills": [ [ "mechanics", 4 ] ], "time": "60 m", "using": [ [ "vehicle_screw", 1 ] ] }, "removal": { "skills": [ [ "mechanics", 2 ] ], "time": "30 m", "using": [ [ "vehicle_screw", 1 ] ] }, diff --git a/data/mods/Craft_Gunpowder/cgp_recipes.json b/data/mods/Craft_Gunpowder/cgp_recipes.json index f73bcb1507c8..4302b8f86dc4 100644 --- a/data/mods/Craft_Gunpowder/cgp_recipes.json +++ b/data/mods/Craft_Gunpowder/cgp_recipes.json @@ -48,108 +48,6 @@ "tools": [ [ [ "chemistry_set", 50 ], [ "hotplate", 50 ], [ "toolset", 50 ] ] ], "components": [ [ [ "oxy_powder", 200 ] ], [ [ "ammonia", 2 ], [ "lye_powder", 200 ] ], [ [ "charcoal", 5 ] ] ] }, - { - "type": "recipe", - "result": "8mm_bootleg", - "category": "CC_AMMO", - "subcategory": "CSC_AMMO_PISTOL", - "skill_used": "fabrication", - "skills_required": [ "cooking", 2 ], - "difficulty": 8, - "time": 45000, - "book_learn": [ [ "recipe_caseless", 5 ], [ "recipe_bullets", 9 ], [ "manual_pistol", 10 ], [ "manual_rifle", 10 ] ], - "qualities": [ { "id": "CHEM", "level": 2 } ], - "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], - "components": [ - [ [ "acid", 1 ] ], - [ [ "plastic_chunk", 5 ] ], - [ [ "oxy_powder", 100 ] ], - [ [ "incendiary", 100 ] ], - [ - [ "lead", 75 ], - [ "gold_small", 75 ], - [ "silver_small", 75 ], - [ "tin", 75 ], - [ "bismuth", 75 ], - [ "solder_wire", 75 ] - ], - [ [ "copper", 35 ] ] - ] - }, - { - "type": "recipe", - "result": "20x66_bootleg_shot", - "category": "CC_AMMO", - "subcategory": "CSC_AMMO_SHOT", - "skill_used": "fabrication", - "skills_required": [ "cooking", 2 ], - "difficulty": 8, - "time": 45000, - "book_learn": [ [ "recipe_caseless", 5 ], [ "recipe_bullets", 9 ], [ "manual_shotgun", 10 ] ], - "qualities": [ { "id": "CHEM", "level": 2 } ], - "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], - "components": [ - [ [ "acid", 1 ] ], - [ [ "plastic_chunk", 4 ] ], - [ [ "oxy_powder", 120 ] ], - [ [ "incendiary", 120 ] ], - [ - [ "lead", 160 ], - [ "gold_small", 160 ], - [ "silver_small", 160 ], - [ "tin", 160 ], - [ "bismuth", 160 ], - [ "solder_wire", 160 ] - ] - ] - }, - { - "type": "recipe", - "result": "20x66_bootleg_flechette", - "category": "CC_AMMO", - "subcategory": "CSC_AMMO_SHOT", - "skill_used": "fabrication", - "skills_required": [ "cooking", 2 ], - "difficulty": 8, - "time": 45000, - "book_learn": [ [ "recipe_caseless", 5 ], [ "recipe_bullets", 9 ], [ "manual_shotgun", 10 ] ], - "qualities": [ { "id": "CHEM", "level": 2 } ], - "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "boltcutters", -1 ], [ "toolset", -1 ] ], [ [ "press", -1 ] ] ], - "components": [ - [ [ "acid", 1 ] ], - [ [ "plastic_chunk", 4 ] ], - [ [ "oxy_powder", 120 ] ], - [ [ "incendiary", 120 ] ], - [ [ "nail", 240 ], [ "combatnail", 240 ] ] - ] - }, - { - "type": "recipe", - "result": "20x66_bootleg_slug", - "category": "CC_AMMO", - "subcategory": "CSC_AMMO_SHOT", - "skill_used": "fabrication", - "skills_required": [ "cooking", 2 ], - "difficulty": 8, - "time": 45000, - "book_learn": [ [ "recipe_caseless", 5 ], [ "recipe_bullets", 9 ], [ "manual_shotgun", 10 ] ], - "qualities": [ { "id": "CHEM", "level": 2 } ], - "tools": [ [ [ "surface_heat", 50, "LIST" ] ], [ [ "press", -1 ] ] ], - "components": [ - [ [ "acid", 1 ] ], - [ [ "plastic_chunk", 4 ] ], - [ [ "oxy_powder", 160 ] ], - [ [ "incendiary", 160 ] ], - [ - [ "lead", 240 ], - [ "gold_small", 240 ], - [ "silver_small", 240 ], - [ "tin", 240 ], - [ "bismuth", 240 ], - [ "solder_wire", 240 ] - ] - ] - }, { "type": "recipe", "result": "smg_9mm", diff --git a/data/mods/Magiclysm/Spells/animist.json b/data/mods/Magiclysm/Spells/animist.json index d437e715b648..9c41387b01d8 100644 --- a/data/mods/Magiclysm/Spells/animist.json +++ b/data/mods/Magiclysm/Spells/animist.json @@ -213,5 +213,78 @@ "min_duration": 6000, "max_duration": 60000, "duration_increment": 2160 + }, + { + "id": "bless", + "type": "SPELL", + "name": { "str": "Bless" }, + "description": "A spell of blessing that gives you energy and boosts your abilities.", + "valid_targets": [ "self", "ally" ], + "flags": [ "VERBAL", "SOMATIC", "NO_LEGS" ], + "effect": "target_attack", + "effect_str": "bless", + "affected_body_parts": [ "torso" ], + "base_casting_time": 100, + "base_energy_cost": 100, + "energy_source": "MANA", + "spell_class": "ANIMIST", + "difficulty": 1, + "max_level": 10, + "min_aoe": 0, + "max_aoe": 5, + "aoe_increment": 0.1, + "min_range": 1, + "max_range": 10, + "range_increment": 2.0, + "//": "duration is in moves", + "min_duration": 6000, + "max_duration": 10000, + "duration_increment": 400 + }, + { + "id": "holy_blade", + "type": "SPELL", + "name": "Holy Blade", + "description": "This blade of light will cut through any evil it makes contact with!", + "valid_targets": [ "self" ], + "flags": [ "VERBAL", "NO_LEGS", "CONCENTRATE" ], + "min_range": 0, + "max_range": 0, + "min_damage": 1, + "max_damage": 1, + "effect": "spawn_item", + "effect_str": "longsword", + "base_casting_time": 350, + "base_energy_cost": 375, + "min_duration": 3000, + "max_duration": 9000, + "duration_increment": 3000, + "difficulty": 5, + "max_level": 20, + "spell_class": "ANIMIST", + "energy_source": "MANA" + }, + { + "id": "spirit_armor", + "type": "SPELL", + "name": "Spiritual Armor", + "description": "Evil will not make it through your defenses if your faith is strong enough!", + "valid_targets": [ "self" ], + "flags": [ "VERBAL", "NO_LEGS", "CONCENTRATE", "SOMATIC" ], + "min_range": 0, + "max_range": 0, + "min_damage": 1, + "max_damage": 1, + "effect": "spawn_item", + "effect_str": "armor_lightplate", + "spell_class": "ANIMIST", + "energy_source": "MANA", + "difficulty": 5, + "max_level": 20, + "base_casting_time": 350, + "base_energy_cost": 375, + "min_duration": 3000, + "max_duration": 9000, + "duration_increment": 3000 } ] diff --git a/data/mods/Magiclysm/Spells/technomancer.json b/data/mods/Magiclysm/Spells/technomancer.json index 47214f73b72f..986644d80633 100644 --- a/data/mods/Magiclysm/Spells/technomancer.json +++ b/data/mods/Magiclysm/Spells/technomancer.json @@ -1,31 +1,4 @@ [ - { - "id": "bless", - "type": "SPELL", - "name": { "str": "Bless" }, - "description": "A spell of blessing that gives you energy and boosts your abilities.", - "valid_targets": [ "self", "ally" ], - "flags": [ "VERBAL", "SOMATIC", "NO_LEGS" ], - "effect": "target_attack", - "effect_str": "bless", - "affected_body_parts": [ "torso" ], - "base_casting_time": 100, - "base_energy_cost": 100, - "energy_source": "MANA", - "spell_class": "TECHNOMANCER", - "difficulty": 1, - "max_level": 10, - "min_aoe": 0, - "max_aoe": 5, - "aoe_increment": 0.1, - "min_range": 1, - "max_range": 10, - "range_increment": 2.0, - "//": "duration is in moves", - "min_duration": 6000, - "max_duration": 10000, - "duration_increment": 400 - }, { "id": "invisibility", "type": "SPELL", @@ -45,52 +18,6 @@ "duration_increment": 250, "max_level": 20 }, - { - "id": "holy_blade", - "type": "SPELL", - "name": "Holy Blade", - "description": "This blade of light will cut through any evil it makes contact with!", - "valid_targets": [ "self" ], - "flags": [ "VERBAL", "NO_LEGS", "CONCENTRATE" ], - "min_range": 0, - "max_range": 0, - "min_damage": 1, - "max_damage": 1, - "effect": "spawn_item", - "effect_str": "longsword", - "base_casting_time": 350, - "base_energy_cost": 375, - "min_duration": 3000, - "max_duration": 9000, - "duration_increment": 3000, - "difficulty": 5, - "max_level": 20, - "spell_class": "TECHNOMANCER", - "energy_source": "MANA" - }, - { - "id": "spirit_armor", - "type": "SPELL", - "name": "Spiritual Armor", - "description": "Evil will not make it through your defenses if your faith is strong enough!", - "valid_targets": [ "self" ], - "flags": [ "VERBAL", "NO_LEGS", "CONCENTRATE", "SOMATIC" ], - "min_range": 0, - "max_range": 0, - "min_damage": 1, - "max_damage": 1, - "effect": "spawn_item", - "effect_str": "armor_lightplate", - "spell_class": "TECHNOMANCER", - "energy_source": "MANA", - "difficulty": 5, - "max_level": 20, - "base_casting_time": 350, - "base_energy_cost": 375, - "min_duration": 3000, - "max_duration": 9000, - "duration_increment": 3000 - }, { "id": "create_atomic_lamp", "type": "SPELL", diff --git a/data/mods/Magiclysm/itemgroups/recipe_books.json b/data/mods/Magiclysm/itemgroups/recipe_books.json index 551bdd13d7a4..d522903b1937 100644 --- a/data/mods/Magiclysm/itemgroups/recipe_books.json +++ b/data/mods/Magiclysm/itemgroups/recipe_books.json @@ -16,6 +16,6 @@ "id": "magic_recipe_advanced", "type": "item_group", "//": "Higher tier recipes, where most school-related recipes require their rune or rune weapon.", - "items": [ [ "magic_armormaking", 30 ] ] + "items": [ [ "magic_armormaking", 30 ], [ "weapon_enchanting_guide", 30 ] ] } ] diff --git a/data/mods/Magiclysm/items/enchanted_melee.json b/data/mods/Magiclysm/items/enchanted_melee.json index 032ebe90f5ea..aab4d0879578 100644 --- a/data/mods/Magiclysm/items/enchanted_melee.json +++ b/data/mods/Magiclysm/items/enchanted_melee.json @@ -89,6 +89,22 @@ "proportional": { "price": 6, "bashing": 1.2, "cutting": 1.2, "weight": 0.8 }, "relative": { "to_hit": 2 } }, + { + "type": "GENERIC", + "id": "sledge_heavy_plus_one", + "copy-from": "hammer_sledge_heavy", + "name": { "str": "heavy sledge hammer +1", "str_pl": "heavy sledge hammers +1" }, + "proportional": { "price": 15.0, "price_postapoc": 30.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "relative": { "to_hit": 1 } + }, + { + "type": "GENERIC", + "id": "sledge_heavy_plus_two", + "copy-from": "hammer_sledge_heavy", + "name": { "str": "heavy sledge hammer +2", "str_pl": "heavy sledge hammers +2" }, + "proportional": { "price": 18.0, "price_postapoc": 36.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "relative": { "to_hit": 2 } + }, { "type": "GENERIC", "id": "warhammer_plus_one", @@ -755,6 +771,22 @@ "proportional": { "price": 6, "bashing": 1.2, "cutting": 1.2, "weight": 0.8 }, "relative": { "to_hit": 2 } }, + { + "type": "GENERIC", + "id": "lucerne_plus_one", + "copy-from": "lucern_hammer", + "name": { "str": "lucerne hammer +1", "str_pl": "lucerne hammers +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "relative": { "to_hit": 1 } + }, + { + "type": "GENERIC", + "id": "lucerne_plus_two", + "copy-from": "lucern_hammer", + "name": { "str": "lucerne hammer +2", "str_pl": "lucerne hammers +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "relative": { "to_hit": 2 } + }, { "id": "rune_biomancer_weapon", "type": "GENERIC", diff --git a/data/mods/Magiclysm/items/enchanted_tools.json b/data/mods/Magiclysm/items/enchanted_tools.json new file mode 100644 index 000000000000..2ca9aca8654b --- /dev/null +++ b/data/mods/Magiclysm/items/enchanted_tools.json @@ -0,0 +1,134 @@ +[ + { + "type": "GENERIC", + "id": "crowbar_plus_one", + "copy-from": "crowbar", + "name": { "str": "crowbar +1", "str_pl": "crowbars +1" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "relative": { "to_hit": 1 }, + "extend": { "qualities": [ [ "PRY", 4 ] ] } + }, + { + "type": "GENERIC", + "id": "crowbar_plus_two", + "copy-from": "crowbar", + "name": { "str": "crowbar +2", "str_pl": "crowbars +2" }, + "proportional": { "price": 9.0, "price_postapoc": 9.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "relative": { "to_hit": 2 }, + "extend": { "qualities": [ [ "PRY", 5 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_hunting_plus_one", + "copy-from": "knife_hunting", + "name": { "str": "hunting knife +1", "str_pl": "hunting knives +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "relative": { "to_hit": 1 }, + "extend": { "qualities": [ [ "BUTCHER", 33 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_hunting_plus_two", + "copy-from": "knife_hunting", + "name": { "str": "hunting knife +2", "str_pl": "hunting knives +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "relative": { "to_hit": 2 }, + "extend": { "qualities": [ [ "BUTCHER", 36 ] ] } + }, + { + "type": "GENERIC", + "id": "jack_plus_one", + "copy-from": "jack", + "name": { "str": "bottle jack +1", "str_pl": "bottle jacks +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "extend": { "qualities": [ [ "JACK", 18 ] ] } + }, + { + "type": "GENERIC", + "id": "jack_plus_two", + "copy-from": "jack", + "name": { "str": "bottle jack +2", "str_pl": "bottle jacks +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "extend": { "qualities": [ [ "JACK", 20 ] ] } + }, + { + "type": "GENERIC", + "id": "scalpel_plus_one", + "copy-from": "scalpel", + "name": { "str": "scalpel +1", "str_pl": "scalpels +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "extend": { "qualities": [ [ "CUT_FINE", 4 ], [ "BUTCHER", 9 ] ] } + }, + { + "type": "GENERIC", + "id": "scalpel_plus_two", + "copy-from": "scalpel", + "name": { "str": "scalpel +2", "str_pl": "scalpels +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "extend": { "qualities": [ [ "CUT_FINE", 5 ], [ "BUTCHER", 10 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_butcher_plus_one", + "copy-from": "knife_butcher", + "name": { "str": "butcher knife +1", "str_pl": "butcher knives +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "extend": { "qualities": [ [ "BUTCHER", 28 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_butcher_plus_two", + "copy-from": "knife_butcher", + "name": { "str": "butcher knife +2", "str_pl": "butcher knives +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "extend": { "qualities": [ [ "BUTCHER", 30 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_meat_cleaver_plus_one", + "copy-from": "knife_meat_cleaver", + "name": { "str": "meat cleaver +1", "str_pl": "meat cleavers +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "extend": { "qualities": [ [ "BUTCHER", 28 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_meat_cleaver_plus_two", + "copy-from": "knife_meat_cleaver", + "name": { "str": "meat cleaver +2", "str_pl": "meat cleavers +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "extend": { "qualities": [ [ "BUTCHER", 30 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_carving_plus_one", + "copy-from": "knife_carving", + "name": { "str": "carving knife +1", "str_pl": "carving knives +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "extend": { "qualities": [ [ "BUTCHER", 24 ] ] } + }, + { + "type": "GENERIC", + "id": "knife_carving_plus_two", + "copy-from": "knife_carving", + "name": { "str": "carving knife +2", "str_pl": "carving knives +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "extend": { "qualities": [ [ "BUTCHER", 26 ] ] } + }, + { + "type": "GENERIC", + "id": "butchering_kit_plus_one", + "copy-from": "butchering_kit", + "name": { "str": "butchering kit +1", "str_pl": "butchering kits +1" }, + "proportional": { "price": 3.0, "price_postapoc": 3.0, "weight": 0.9, "bashing": 1.1, "cutting": 1.1 }, + "extend": { "qualities": [ [ "BUTCHER", 41 ] ] } + }, + { + "type": "GENERIC", + "id": "butchering_kit_plus_two", + "copy-from": "butchering_kit", + "name": { "str": "butchering kit +2", "str_pl": "butchering kits +2" }, + "proportional": { "price": 6.0, "price_postapoc": 6.0, "weight": 0.8, "bashing": 1.2, "cutting": 1.2 }, + "extend": { "qualities": [ [ "BUTCHER", 45 ] ] } + } +] diff --git a/data/mods/Magiclysm/items/recipe_books.json b/data/mods/Magiclysm/items/recipe_books.json index 3d0f96db1c59..1de5f8194174 100644 --- a/data/mods/Magiclysm/items/recipe_books.json +++ b/data/mods/Magiclysm/items/recipe_books.json @@ -151,5 +151,25 @@ "intelligence": 10, "time": "25 m", "fun": -1 + }, + { + "id": "weapon_enchanting_guide", + "type": "BOOK", + "looks_like": "welding_book", + "name": { "str": "Enchanter's Guidebook", "str_pl": "copies of Enchanter's Guidebooks" }, + "description": "A hefty textbook on the theory and practice of magically strengthening weapons and tools.", + "weight": "750 g", + "volume": "1250 ml", + "price": 9400, + "price_postapoc": 4250, + "material": [ "paper" ], + "symbol": "?", + "color": "blue", + "skill": "fabrication", + "required_level": 5, + "max_level": 6, + "intelligence": 10, + "time": "60 m", + "fun": -1 } ] diff --git a/data/mods/Magiclysm/monsters/demon_spider.json b/data/mods/Magiclysm/monsters/demon_spider.json index cc5fdd31357a..951474e63c5a 100644 --- a/data/mods/Magiclysm/monsters/demon_spider.json +++ b/data/mods/Magiclysm/monsters/demon_spider.json @@ -34,17 +34,17 @@ "diff": 2, "volume": "30000 ml", "weight": "40750 g", - "hp": 45, + "hp": 30, "speed": 150, "symbol": "s", "color": "red", "aggression": -10, "morale": 100, - "melee_skill": 6, + "melee_skill": 3, "melee_dice": 1, "melee_dice_sides": 8, "melee_cut": 4, - "dodge": 7, + "dodge": 3, "armor_bash": 1, "armor_cut": 8, "armor_stab": 8, @@ -71,17 +71,17 @@ "weight": "125 kg", "//": "monster can't be any bigger because of limits of volume on tiles. if there is a way designed around this, it should be about 3500 L", "volume": "1000 L", - "hp": 435, + "hp": 325, "speed": 95, "symbol": "S", "color": "red", "aggression": 50, "morale": 100, - "melee_skill": 9, - "melee_dice": 20, - "melee_dice_sides": 8, + "melee_skill": 5, + "melee_dice": 5, + "melee_dice_sides": 10, "melee_cut": 12, - "dodge": 4, + "dodge": 1, "armor_bash": 5, "armor_cut": 45, "armor_stab": 60, @@ -103,16 +103,16 @@ "description": "This gigantic spider is the size of a moving van: you have no idea how it manages to stay together, much less move with that bulk. Its abdomen is huge and swollen-looking, and an evil intelligence burns in its eyes even as magic crackles around its chitinous barbs.", "copy-from": "mon_demon_spider", "weight": "250 kg", - "hp": 5600, - "speed": 28, + "hp": 1400, + "speed": 25, "aggression": 100, - "melee_skill": 10, + "melee_skill": 8, "melee_dice_sides": 20, "melee_cut": 30, "vision_day": 12, "vision_night": 18, "harvest": "demon_spider_queen", "flags": [ "SEES", "SMELLS", "HEARS", "VENOM", "WEBWALK", "CLIMBS", "HARDTOSHOOT", "PUSH_MON", "STUN_IMMUNE" ], - "special_attacks": [ { "type": "spell", "spell_data": { "id": "mon_summon_demon_spiderlings" }, "cooldown": 14 } ] + "special_attacks": [ { "type": "spell", "spell_data": { "id": "mon_summon_demon_spiderlings" }, "cooldown": 256 } ] } ] diff --git a/data/mods/Magiclysm/monsters/golems.json b/data/mods/Magiclysm/monsters/golems.json index cd3499e0deca..6701b7705778 100644 --- a/data/mods/Magiclysm/monsters/golems.json +++ b/data/mods/Magiclysm/monsters/golems.json @@ -15,7 +15,7 @@ "material": [ "clay" ], "symbol": "X", "color": "brown", - "aggression": 10, + "aggression": 8, "morale": 100, "melee_skill": 6, "melee_dice": 2, @@ -76,7 +76,7 @@ "material": [ "stone" ], "symbol": "X", "color": "light_gray", - "aggression": 10, + "aggression": 8, "morale": 100, "melee_skill": 6, "melee_dice": 3, @@ -110,7 +110,7 @@ "material": [ "iron" ], "symbol": "X", "color": "dark_gray", - "aggression": 10, + "aggression": 9, "morale": 100, "melee_skill": 6, "melee_dice": 3, diff --git a/data/mods/Magiclysm/monsters/monsters.json b/data/mods/Magiclysm/monsters/monsters.json index a604ed8a2e02..c50811e1dba4 100644 --- a/data/mods/Magiclysm/monsters/monsters.json +++ b/data/mods/Magiclysm/monsters/monsters.json @@ -14,7 +14,7 @@ "material": [ "flesh" ], "symbol": "W", "color": "brown", - "aggression": 100, + "aggression": 8, "morale": 100, "melee_skill": 6, "melee_dice": 5, @@ -25,6 +25,7 @@ "armor_cut": 2, "armor_bullet": 2, "vision_night": 20, + "anger_triggers": [ "HURT", "PLAYER_NEAR_BABY", "PLAYER_CLOSE" ], "path_settings": { "max_dist": 25 }, "harvest": "owlbear", "reproduction": { "baby_egg": "egg_owlbear_rock", "baby_count": 1, "baby_timer": 20 }, @@ -49,7 +50,8 @@ "hp": 100, "speed": 75, "phase": "LIQUID", - "aggression": 100, + "aggression": 8, + "anger_triggers": [ "HURT", "PLAYER_CLOSE" ], "morale": 100, "melee_skill": 5, "melee_dice": 2, @@ -234,7 +236,8 @@ "material": [ "flesh" ], "symbol": "T", "color": "light_green", - "aggression": 100, + "aggression": 8, + "anger_triggers": [ "HURT", "PLAYER_CLOSE" ], "morale": 100, "melee_skill": 5, "melee_dice": 5, diff --git a/data/mods/Magiclysm/professions.json b/data/mods/Magiclysm/professions.json index b54c8499f03a..0ce1bb613ff0 100644 --- a/data/mods/Magiclysm/professions.json +++ b/data/mods/Magiclysm/professions.json @@ -29,7 +29,7 @@ "id": "druid", "name": "Druid", "description": "The ancient circle of druids is gone with the Cataclysm. Nature must thrive.", - "points": 4, + "points": 2, "items": { "both": [ "druid_spellbook", "leathersandals", "robe", "rope_makeshift_30", "hide_bag", "hat_fur", "gloves_wraps_fur" ] }, diff --git a/data/mods/Magiclysm/qualities.json b/data/mods/Magiclysm/qualities.json index 8d780880aa49..d4425faa8100 100644 --- a/data/mods/Magiclysm/qualities.json +++ b/data/mods/Magiclysm/qualities.json @@ -12,7 +12,8 @@ "CSC_ENCHANTED_POTIONS", "CSC_ENCHANTED_RUNES", "CSC_ENCHANTED_MODS", - "CSC_ENCHANTED_OTHER" + "CSC_ENCHANTED_OTHER", + "CSC_ENCHANTED_ENCHANTING" ] }, { diff --git a/data/mods/Magiclysm/recipes/enchanting.json b/data/mods/Magiclysm/recipes/enchanting.json new file mode 100644 index 000000000000..40e3779df36d --- /dev/null +++ b/data/mods/Magiclysm/recipes/enchanting.json @@ -0,0 +1,723 @@ +[ + { + "type": "recipe", + "result": "cestus_plus_one", + "category": "CC_ENCHANTED", + "subcategory": "CSC_ENCHANTED_ENCHANTING", + "skill_used": "fabrication", + "difficulty": 6, + "time": "3 h", + "autolearn": false, + "reversible": false, + "book_learn": [ [ "weapon_enchanting_guide", 6 ] ], + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "components": [ [ [ "cestus", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "cestus_plus_two", + "components": [ [ [ "cestus_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "flaming_fist_plus_one", + "components": [ [ [ "flaming_fist", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "flaming_fist_plus_two", + "components": [ [ [ "flaming_fist_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "crowbar_plus_one", + "components": [ [ [ "crowbar", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "crowbar_plus_two", + "components": [ [ [ "crowbar_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "knife_hunting_plus_one", + "components": [ [ [ "knife_hunting", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "knife_hunting_plus_two", + "components": [ [ [ "knife_hunting_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "jack_plus_one", + "components": [ [ [ "jack", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "jack_plus_two", + "components": [ [ [ "jack_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "scalpel_plus_one", + "components": [ [ [ "scalpel", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "scalpel_plus_two", + "components": [ [ [ "scalpel_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "knife_butcher_plus_one", + "components": [ [ [ "knife_butcher", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "knife_butcher_plus_two", + "components": [ [ [ "knife_butcher_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "knife_meat_cleaver_plus_one", + "components": [ [ [ "knife_meat_cleaver", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "knife_meat_cleaver_plus_two", + "components": [ [ [ "knife_meat_cleaver_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "knife_carving_plus_one", + "components": [ [ [ "knife_carving", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "knife_carving_plus_two", + "components": [ [ [ "knife_carving_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "cudgel_plus_one", + "components": [ [ [ "cudgel", 1 ] ], [ [ "mana_dust", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "cudgel_plus_two", + "components": [ [ [ "cudgel_plus_one", 1 ] ], [ [ "mana_dust", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "q_staff_plus_one", + "components": [ [ [ "q_staff", 1 ] ], [ [ "mana_dust", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "q_staff_plus_two", + "components": [ [ [ "q_staff_plus_one", 1 ] ], [ [ "mana_dust", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "i_staff_plus_one", + "components": [ [ [ "i_staff", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "i_staff_plus_two", + "components": [ [ [ "i_staff_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "longsword_plus_one", + "components": [ [ [ "longsword", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "longsword_plus_two", + "components": [ [ [ "longsword_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "sledge_plus_one", + "components": [ [ [ "hammer_sledge", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "sledge_plus_two", + "components": [ [ [ "sledge_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "sledge_heavy_plus_one", + "components": [ [ [ "hammer_sledge_heavy", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "sledge_heavy_plus_two", + "components": [ [ [ "sledge_heavy_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "warhammer_plus_one", + "components": [ [ [ "warhammer", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "warhammer_plus_two", + "components": [ [ [ "warhammer_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "bat_plus_one", + "components": [ [ [ "bat", 1 ] ], [ [ "mana_dust", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "bat_plus_two", + "components": [ [ [ "bat_plus_one", 1 ] ], [ [ "mana_dust", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "bat_metal_plus_one", + "components": [ [ [ "bat_metal", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "bat_metal_plus_two", + "components": [ [ [ "bat_metal_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "spear_steel_plus_one", + "components": [ [ [ "spear_steel", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "spear_steel_plus_two", + "components": [ [ [ "spear_steel_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "qiang_plus_one", + "components": [ [ [ "qiang", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "qiang_plus_two", + "components": [ [ [ "qiang_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "halberd_plus_one", + "components": [ [ [ "halberd", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "halberd_plus_two", + "components": [ [ [ "halberd_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "glaive_plus_one", + "components": [ [ [ "glaive", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "glaive_plus_two", + "components": [ [ [ "glaive_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "naginata_plus_one", + "components": [ [ [ "naginata", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "naginata_plus_two", + "components": [ [ [ "naginata_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "mace_plus_one", + "components": [ [ [ "mace", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "mace_plus_two", + "components": [ [ [ "mace_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "morningstar_plus_one", + "components": [ [ [ "morningstar", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "morningstar_plus_two", + "components": [ [ [ "morningstar_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "jian_plus_one", + "components": [ [ [ "jian", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "jian_plus_two", + "components": [ [ [ "jian_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "scimitar_plus_one", + "components": [ [ [ "scimitar", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "scimitar_plus_two", + "components": [ [ [ "scimitar_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "estoc_plus_one", + "components": [ [ [ "estoc", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "estoc_plus_two", + "components": [ [ [ "estoc_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "arming_sword_plus_one", + "components": [ [ [ "arming_sword", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "arming_sword_plus_two", + "components": [ [ [ "arming_sword_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "broadsword_plus_one", + "components": [ [ [ "broadsword", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "broadsword_plus_two", + "components": [ [ [ "broadsword_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "battleaxe_plus_one", + "components": [ [ [ "battleaxe", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "battleaxe_plus_two", + "components": [ [ [ "battleaxe_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "cavalry_sabre_plus_one", + "components": [ [ [ "cavalry_sabre", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "cavalry_sabre_plus_two", + "components": [ [ [ "cavalry_sabre_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "cutlass_plus_one", + "components": [ [ [ "cutlass", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "cutlass_plus_two", + "components": [ [ [ "cutlass_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "fire_ax_plus_one", + "components": [ [ [ "fire_ax", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "fire_ax_plus_two", + "components": [ [ [ "fire_ax_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "katana_plus_one", + "components": [ [ [ "katana", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "katana_plus_two", + "components": [ [ [ "katana_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "knife_combat_plus_one", + "components": [ [ [ "knife_combat", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "knife_combat_plus_two", + "components": [ [ [ "knife_combat_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "knife_rambo_plus_one", + "components": [ [ [ "knife_rambo", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "knife_rambo_plus_two", + "components": [ [ [ "knife_rambo_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "knife_trench_plus_one", + "components": [ [ [ "knife_trench", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "knife_trench_plus_two", + "components": [ [ [ "knife_trench_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "kris_plus_one", + "components": [ [ [ "kris", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "kris_plus_two", + "components": [ [ [ "kris_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "kukri_plus_one", + "components": [ [ [ "kukri", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "kukri_plus_two", + "components": [ [ [ "kukri_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "nodachi_plus_one", + "components": [ [ [ "nodachi", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "nodachi_plus_two", + "components": [ [ [ "nodachi_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "pickaxe_plus_one", + "components": [ [ [ "pickaxe", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "pickaxe_plus_two", + "components": [ [ [ "pickaxe_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "pike_plus_one", + "components": [ [ [ "pike", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "pike_plus_two", + "components": [ [ [ "pike_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "rapier_plus_one", + "components": [ [ [ "rapier", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "rapier_plus_two", + "components": [ [ [ "rapier_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "tanto_plus_one", + "components": [ [ [ "tanto", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "tanto_plus_two", + "components": [ [ [ "tanto_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "wakizashi_plus_one", + "components": [ [ [ "wakizashi", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "wakizashi_plus_two", + "components": [ [ [ "wakizashi_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "zweihander_plus_one", + "components": [ [ [ "zweihander", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "zweihander_plus_two", + "components": [ [ [ "zweihander_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "khopesh_plus_one", + "components": [ [ [ "khopesh", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "khopesh_plus_two", + "components": [ [ [ "khopesh_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "sword_xiphos_plus_one", + "components": [ [ [ "sword_xiphos", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "sword_xiphos_plus_two", + "components": [ [ [ "sword_xiphos_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "dao_plus_one", + "components": [ [ [ "dao", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "dao_plus_two", + "components": [ [ [ "dao_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 1 } ], + "result": "lucerne_plus_one", + "components": [ [ [ "lucern_hammer", 1 ] ], [ [ "mana_dust", 20 ] ], [ [ "mercury", 10 ] ] ] + }, + { + "type": "recipe", + "copy-from": "cestus_plus_one", + "qualities": [ { "id": "MANA_INFUSE", "level": 2 } ], + "result": "lucerne_plus_two", + "components": [ [ [ "lucerne_plus_one", 1 ] ], [ [ "mana_dust", 40 ] ], [ [ "mercury", 20 ] ] ] + } +] diff --git a/data/mods/Magiclysm/recipes/magic_tools.json b/data/mods/Magiclysm/recipes/magic_tools.json index ac63cd0c47e6..dbe83d6cf792 100644 --- a/data/mods/Magiclysm/recipes/magic_tools.json +++ b/data/mods/Magiclysm/recipes/magic_tools.json @@ -101,5 +101,39 @@ [ [ "pipe", 3 ] ], [ [ "crystallized_mana", 80 ] ] ] + }, + { + "result": "butchering_kit_plus_one", + "type": "recipe", + "category": "CC_OTHER", + "subcategory": "CSC_OTHER_TOOLS", + "skill_used": "fabrication", + "reversible": true, + "time": "30 s", + "autolearn": true, + "components": [ + [ [ "knife_butcher_plus_one", 1 ] ], + [ [ "knife_carving_plus_one", 1 ] ], + [ [ "knife_meat_cleaver_plus_one", 1 ] ], + [ [ "leather", 2 ], [ "rag", 2 ] ], + [ [ "string_6", 2 ], [ "cordage_6", 2 ] ] + ] + }, + { + "result": "butchering_kit_plus_two", + "type": "recipe", + "category": "CC_OTHER", + "subcategory": "CSC_OTHER_TOOLS", + "skill_used": "fabrication", + "reversible": true, + "time": "30 s", + "autolearn": true, + "components": [ + [ [ "knife_butcher_plus_two", 1 ] ], + [ [ "knife_carving_plus_two", 1 ] ], + [ [ "knife_meat_cleaver_plus_two", 1 ] ], + [ [ "leather", 2 ], [ "rag", 2 ] ], + [ [ "string_6", 2 ], [ "cordage_6", 2 ] ] + ] } ] diff --git a/data/mods/Magiclysm/requirements/cooking_components.json b/data/mods/Magiclysm/requirements/cooking_components.json index 24a28514f5c0..8628d93a98df 100644 --- a/data/mods/Magiclysm/requirements/cooking_components.json +++ b/data/mods/Magiclysm/requirements/cooking_components.json @@ -10,7 +10,8 @@ [ "human_flesh", 1 ], [ "mutant_human_flesh", 1 ], [ "purified_meat", 1 ], - [ "impure_meat", 1 ] + [ "impure_meat", 1 ], + [ "meat_dragon", 1 ] ] ] } diff --git a/data/mods/saveload_lua_test/finalize.lua b/data/mods/saveload_lua_test/finalize.lua new file mode 100644 index 000000000000..8cb4e109d3a7 --- /dev/null +++ b/data/mods/saveload_lua_test/finalize.lua @@ -0,0 +1 @@ +gdebug.log_info("SLT: finalize") diff --git a/data/mods/saveload_lua_test/main.lua b/data/mods/saveload_lua_test/main.lua new file mode 100644 index 000000000000..e97c53ea9566 --- /dev/null +++ b/data/mods/saveload_lua_test/main.lua @@ -0,0 +1,51 @@ +gdebug.log_info("SLT: main") + +local mod = game.mod_runtime[ game.current_mod ] +local storage = game.mod_storage[ game.current_mod ] + +--[[ + If we keep all our data simple and in mod.storage, + we won't even have to register save/load hooks, + it'll be saved/loaded automatically. +]]-- +mod.storage = storage + +--[[ + The following values are default, they'll be assigned on + new game start or on game init before save is loaded. +]] +-- Numeric data +storage.num = 12.3 +-- Usertype +storage.tri = Tripoint.new(3, 4, 5) +-- String +storage.tri_as_str = tostring( Tripoint.new(3, 4, 5) ) + +--[[ + If we want to build complex state out of loaded data + we may create a hook that would read loaded data from mod_storage + and create our complex state in the mod_runtime. +]]-- +mod.on_game_load_hook = function() + gdebug.log_info("SLT: on_load") + + if storage.num then + gdebug.log_info( "Data found! num = ", storage.num ) + end + if storage.tri then + gdebug.log_info( "Data found! tri = ", storage.tri ) + end +end + +--[[ + If we have complex enough state (e.g. recursive tables, or with custom metatables) + we may create a hook that would write a simplified version into mod_storage, + so the hardcoded JSON serializer would be able to handle it. +]]-- +mod.on_game_save_hook = function() + gdebug.log_info("SLT: on_save") + + if storage.num then + gdebug.log_info("Saving NUM value = ", storage.num) + end +end diff --git a/data/mods/saveload_lua_test/modinfo.json b/data/mods/saveload_lua_test/modinfo.json new file mode 100644 index 000000000000..ff7e2603b31d --- /dev/null +++ b/data/mods/saveload_lua_test/modinfo.json @@ -0,0 +1,14 @@ +[ + { + "type": "MOD_INFO", + "id": "saveload_lua_test", + "name": "SaveLoad Lua Test", + "authors": [ "Olanti" ], + "description": "Mod for testing Lua save/load API.", + "category": "content", + "lua_api_version": 1, + "//": "It's not really obsolete, but it's useful only for devs and modders, and not for player.", + "obsolete": true, + "dependencies": [ "bn" ] + } +] diff --git a/data/mods/saveload_lua_test/preload.lua b/data/mods/saveload_lua_test/preload.lua new file mode 100644 index 000000000000..fa895d2770a1 --- /dev/null +++ b/data/mods/saveload_lua_test/preload.lua @@ -0,0 +1,11 @@ +gdebug.log_info("SLT: preload") + +local mod = game.mod_runtime[ game.current_mod ] + +game.hooks.on_game_load[ #game.hooks.on_game_load + 1 ] = function( ... ) + return mod.on_game_load_hook( ... ) +end + +game.hooks.on_game_save[ #game.hooks.on_game_save + 1 ] = function( ... ) + return mod.on_game_save_hook( ... ) +end diff --git a/data/mods/smart_house_remotes/finalize.lua b/data/mods/smart_house_remotes/finalize.lua new file mode 100644 index 000000000000..7f5f8fe40b84 --- /dev/null +++ b/data/mods/smart_house_remotes/finalize.lua @@ -0,0 +1,4 @@ +gdebug.log_info("SHR: finalize.") + +-- We're not finalizing anything. +-- Besides, there's no finalizing API available yet. diff --git a/data/mods/smart_house_remotes/item.json b/data/mods/smart_house_remotes/item.json new file mode 100644 index 000000000000..4ec2b094ffa2 --- /dev/null +++ b/data/mods/smart_house_remotes/item.json @@ -0,0 +1,35 @@ +[ + { + "id": "smart_house_remote", + "type": "TOOL", + "category": "tools", + "name": { "str": "smart house remote" }, + "description": "A small remote with lcd display used to control garage doors and window curtains. Completely useless now, unless you manage to restore power to the house.", + "weight": "100 g", + "volume": "300 ml", + "price": 1000, + "price_postapoc": 1000, + "bashing": 1, + "material": [ "plastic", "aluminum" ], + "symbol": ";", + "color": "light_blue", + "ammo": "battery", + "charges_per_use": 1, + "use_action": "SMART_HOUSE_REMOTE", + "magazines": [ + [ + "battery", + [ + "light_battery_cell", + "light_plus_battery_cell", + "light_minus_battery_cell", + "light_atomic_battery_cell", + "light_minus_atomic_battery_cell", + "light_minus_disposable_cell", + "light_disposable_cell" + ] + ] + ], + "magazine_well": "250 ml" + } +] diff --git a/data/mods/smart_house_remotes/item_group.json b/data/mods/smart_house_remotes/item_group.json new file mode 100644 index 000000000000..7158820cde77 --- /dev/null +++ b/data/mods/smart_house_remotes/item_group.json @@ -0,0 +1,8 @@ +[ + { + "type": "item_group", + "id": "SUS_junk_drawer", + "subtype": "collection", + "entries": [ { "item": "smart_house_remote", "count": 1, "prob": 70 } ] + } +] diff --git a/data/mods/smart_house_remotes/iuse.json b/data/mods/smart_house_remotes/iuse.json new file mode 100644 index 000000000000..12ca2f8482b7 --- /dev/null +++ b/data/mods/smart_house_remotes/iuse.json @@ -0,0 +1,7 @@ +[ + { + "type": "item_action", + "id": "SMART_HOUSE_REMOTE", + "name": { "str": "Control doors and shutters" } + } +] diff --git a/data/mods/smart_house_remotes/main.lua b/data/mods/smart_house_remotes/main.lua new file mode 100644 index 000000000000..8d675e25b3d2 --- /dev/null +++ b/data/mods/smart_house_remotes/main.lua @@ -0,0 +1,407 @@ +gdebug.log_info("SHR: main.") + +--[[ + Main script. + This file can be loaded multiple times (e.g. when you press a key to + hot-reload Lua code), so ideally we shouldn't modify here any state defined + in earlier load stages. +]]-- + +local mod = game.mod_runtime[ game.current_mod ] + +--[[ + When we export Lua function, Lua is smart enough not to garbage collect + local variables and functions that our exported function (closure) depends on. + So, why do we put everything into the mod runtime table anyway? + Well, to allow mod interoperability, of course! + Say, a mod decided to add an item action that reconfigures existing smart remote. + It could hack together a copy of our 'set_remote_base' function of course, + but it's much easier (and reliable) to just grab it from globally available + game.mod_runtime.smart_house_remote_mod.set_remote_base +]] + +-- Item id of the remote +mod.item_id = "smart_house_remote" + +-- Variable id to store remote's base omt +mod.var_base = "shr_base" + +-- Range of remote, horizontal +mod.remote_wireless_range = 24 + +-- Range of remote, vertical +mod.remote_wireless_range_z = 2 + +-- Get abs omt of remote's base +mod.get_remote_base_omt = function( item ) + return item:get_var_tri( mod.var_base, Tripoint.new(0,0,0) ) +end + +-- Get abs ms of remote's base +mod.get_remote_base_abs_ms = function( item ) + local p_omt = mod.get_remote_base_omt( item ) + return coords.omt_to_ms( p_omt ) + Point.new( const.OMT_MS_SIZE // 2, const.OMT_MS_SIZE // 2 ) +end + +-- Set remote's base abs omt +mod.set_remote_base = function( item, p_omt ) + item:set_var_tri(mod.var_base, p_omt) +end + +-- Look for spawned remotes and bind them to given omt +mod.on_mapgen_postprocess_hook = function( map, p_omt, when ) + local mapsize = map:get_map_size() + local item_id = mod.item_id + for y = 0, mapsize-1 do + for x = 0,mapsize-1 do + local p = Tripoint.new(x, y, 0) + -- TODO: Check whether using has_items_at() gives a speedup in Lua. + -- In C++, it's supposed to be faster then !i_at( p ).empty() + if map:has_items_at( p ) then + local items = map:get_items_at( p ):as_item_stack() + for _, item in pairs(items) do + if item:get_type():str() == item_id then + mod.set_remote_base( item, p_omt ) + end + end + end + end + end +end + +-- List of terrain transformations supported by the mod +mod.get_transform_list = function() + return { + { + -- terrain id when open + o = 't_window_domestic', + -- terrain id when closed + c = 't_curtains', + -- terrain id that belongs to this group, but can't be closed/opened + -- TODO: some 'inert' tiles can belong to multiple transforms + i = { + 't_window', + 't_window_frame', + 't_window_open', + 't_window_empty', + 't_window_no_curtains', + 't_window_no_curtains_open' + }, + -- action name in UI + name_open = locale.gettext('Open curtains'), + name_close = locale.gettext('Close curtains'), + -- power required to open or close + power = 5, + }, + { + -- TODO: garage doors should check whether there's something obstructing them. + o = 't_door_metal_locked_o', + c = 't_door_metal_locked', + name_open = locale.gettext('Raise garage door'), + name_close = locale.gettext('Lower garage door'), + power = 20, + } + } +end + +-- Caches transforms list for lookups +mod.cache_transforms = function(tlist) + local to_close_list = {} + local to_open_list = {} + local idx = 0 + for _,v in pairs(tlist) do + idx = idx + 1 + to_open_list[v.c] = idx + to_close_list[v.o] = idx + end + return to_close_list, to_open_list +end + +-- These 2 functions use breadth-first search to find all tiles belonging to given block +mod.get_neighbours_at = function( opts, block, p ) + local k = tostring(p) + local v = opts[k] + if v ~= nil and v.idx == block.idx then + opts[k] = nil + block.points[#block.points + 1] = p + if v.can_open then + block.can_open_num = block.can_open_num + 1 + end + if v.can_close then + block.can_close_num = block.can_close_num + 1 + end + mod.get_neighbours( opts, block, p ) + end +end +mod.get_neighbours = function( opts, block, p ) + mod.get_neighbours_at( opts, block, p + Tripoint.new(1, 0, 0) ) + mod.get_neighbours_at( opts, block, p + Tripoint.new(-1, 0, 0) ) + mod.get_neighbours_at( opts, block, p + Tripoint.new(0, 1, 0) ) + mod.get_neighbours_at( opts, block, p + Tripoint.new(0, -1, 0) ) +end + +-- Helper func to check whether value is in array +local find_in_array = function( arr, val ) + for k, v in pairs( arr ) do + if v == val then + return k + end + end + return nil +end + +-- Helper func to check whether tile is considered as inert for one of the blocks +local check_is_tile_inert = function( tlist, val ) + for idx, transform in pairs(tlist) do + if transform.i and find_in_array( transform.i, val ) then + return idx + end + end + return nil +end + +--[[ + Look for multitile 'blocks' in given omt (e.g. a multitile window, or a multitile garage door). + Returns array of tables: + { + idx = int, --Index of transform entry in transforms list + points = {}, --Array of points that belong to the multitile + can_open_num = int, --Number of tiles that can be opened + can_close_num = int, --Number of tiles that can be closed + can_open = bool, --Whether block can be opened + can_close = bool, --Whether block can be closed + } +]]-- +mod.build_target_list = function( map, pos_omt ) + -- First, find all tiles that can be opened, closed or belong to 'inert' group + local act_tiles = {} + local tlist = mod.get_transform_list() + local to_close_list, to_open_list = mod.cache_transforms(tlist) + local p_zero = map:get_local_ms( coords.omt_to_ms( pos_omt ) ) + local iter_max = const.OMT_MS_SIZE - 1 + for y = 0, iter_max do + for x = 0, iter_max do + local p = p_zero + Tripoint.new(x, y, 0) + local t = map:get_ter_at( p ):str_id() + + local idx_found = to_close_list[t:str()] + local can_open = false + local can_close = false + if idx_found then + can_close = true + else + idx_found = to_open_list[t:str()] + if idx_found then + can_open = true + else + idx_found = check_is_tile_inert( tlist, t:str() ) + end + end + + if idx_found then + act_tiles[tostring(p)] = { p = p, idx = idx_found, can_open = can_open, can_close = can_close } + end + end + end + + -- Use breadth-first to sort tiles into multitile blocks + local ret = {} + + local next = next + -- While (table has entries) do + while next(act_tiles) ~= nil do + -- Remove first available entry from table + local k, v = next(act_tiles) + act_tiles[k] = nil + + -- Build block of neighboring tiles with same idx + local block = { + points = { v.p }, + idx = v.idx, + can_open_num = v.can_open and 1 or 0, + can_close_num = v.can_close and 1 or 0 + } + mod.get_neighbours( act_tiles, block, v.p ) + block.can_open = block.can_open_num > 0 + block.can_close = block.can_close_num > 0 + + -- Add block to list + ret[#ret + 1] = block + end + + return ret +end + +-- Close all closable tiles in block +mod.block_close = function( block, transform ) + for _, p in pairs(block.points) do + local ter_at_p = gapi.get_map():get_ter_at( p ):str_id() + if ter_at_p:str() == transform.o then + gapi.get_map():set_ter_at( p, TerId.new( transform.c ):int_id() ) + end + end +end + +-- Open all openable tiles in block +mod.block_open = function( block, transform ) + for _, p in pairs(block.points) do + local ter_at_p = gapi.get_map():get_ter_at( p ):str_id() + if ter_at_p:str() == transform.c then + gapi.get_map():set_ter_at( p, TerId.new( transform.o ):int_id() ) + end + end +end + +-- Show 'not enough power' error +mod.show_low_power_error = function() + local pp = QueryPopup.new() + --~ Message on the remote, stylized as calculator led display. + --~ Shown when there's not enough grid charge. + pp:message(locale.gettext("Low Current At Endpoint")) + -- This color is awful, but it's a cheap LCD display, what did you expect? + pp:message_color( Color.i_green ) + pp:allow_any_key( true ) + pp:query() +end + +-- Show 'no signal' error +mod.show_no_signal_error = function() + local pp = QueryPopup.new() + --~ Message on the remote, stylized as calculator led display. + --~ Shown when player is too far away from the area. + pp:message(locale.gettext("No Signal")) + pp:message_color( Color.i_green ) + pp:allow_any_key( true ) + pp:query() +end + +-- Show 'no valid blocks' error +mod.show_no_endpoints_error = function() + local pp = QueryPopup.new() + --~ Message on the remote, stylized as calculator led display. + --~ Shown when there's nothing to activate. + pp:message(locale.gettext("No Endpoints Available")) + pp:message_color( Color.i_green ) + pp:allow_any_key( true ) + pp:query() +end + +-- Add message indicating the remote works +mod.show_msg_remote_working = function() + gapi.add_msg(locale.gettext("The remote beeps quietly.")) +end + +-- Open or close all tiles in block +mod.invoke_block = function( block, grid ) + local tlist = mod.get_transform_list() + local transform = tlist[ block.idx ] + local power_available = grid:get_resource( true ) + + if block.can_open then + local power_needed = transform.power * block.can_open_num + if power_needed > power_available then + mod.show_low_power_error() + return 0 + end + grid:mod_resource( -power_needed, true ) + mod.block_open( block, transform ) + elseif block.can_close then + local power_needed = transform.power * block.can_close_num + if power_needed > power_available then + mod.show_low_power_error() + return 0 + end + grid:mod_resource( -power_needed, true ) + mod.block_close( block, transform ) + end + return 1 +end + +-- Main iuse function. Returns amount of charges consumed from item. +mod.iuse_function = function( who, item, pos ) + local user_pos = gapi.get_map():get_abs_ms( pos ) + + -- Uncomment this so on activation the remote reconfigures itself to work in user's omt + --[[ + mod.set_remote_base( item, coords.ms_to_omt( user_pos ) ) + gapi.add_msg(locale.gettext("Remote reconfigured!")) + --if true then + -- return 0 + --end + ]] + + local base_pos = mod.get_remote_base_abs_ms( item ) + + -- Check distance to wireless base the remote is bound to. + -- The base does not physically exist in game world, but we imagine + -- it's tucked away into a hoouse wall or something. + if math.abs( user_pos.z - base_pos.z ) > mod.remote_wireless_range_z or + coords.rl_dist( user_pos, base_pos ) > mod.remote_wireless_range then + mod.show_no_signal_error() + return 0 + end + + local base_pos_omt = mod.get_remote_base_omt( item ) + local grid = gapi.get_distribution_grid_tracker():get_grid_at_abs_ms( base_pos ); + local power_available = grid:get_resource( true ) + + -- If house has no power, the wireless base also has no power and can't emit signal. + if power_available == 0 then + mod.show_no_signal_error() + return 0 + end + + -- Get list of all available multitile formations in base's omt + local targets = mod.build_target_list( gapi.get_map(), base_pos_omt ) + + -- Ignore ones that are completely inert (e.g. window got all its curtains torn down). + local sel_list = {} + local transforms = mod.get_transform_list() + for block_idx, block in pairs(targets) do + if block.can_open then + sel_list[#sel_list + 1] = { + block = block, + do_open = true, + text = transforms[block.idx].name_open.." #"..tostring(block_idx) + } + elseif block.can_close then + sel_list[#sel_list + 1] = { + block = block, + do_open = false, + text = transforms[block.idx].name_close.." #"..tostring(block_idx) + } + end + end + + -- No available blocks? Too bad. + if next(sel_list) == nil then + mod.show_no_endpoints_error() + return 0 + end + + -- If only 1 is available, don't ask + if #sel_list == 1 then + mod.show_msg_remote_working() + return mod.invoke_block( sel_list[1].block, grid ) + end + + -- Query which block to activate + local ui = UiList.new() + --~ Title of the menu prompting player to select what to activate with the remote. + --~ Typically it's doors, garage doors or window curtains. + ui:title(locale.gettext("Select endpoint")) + for i = 1, #sel_list do + ui:add( i, sel_list[i].text ) + end + local eidx = ui:query() + + -- Canceled by player + if eidx < 1 then + gapi.add_msg(locale.gettext("Nevermind.")) + return 0 + end + + -- Activate desired block + mod.show_msg_remote_working() + return mod.invoke_block( sel_list[eidx].block, grid ) +end diff --git a/data/mods/smart_house_remotes/modinfo.json b/data/mods/smart_house_remotes/modinfo.json new file mode 100644 index 000000000000..fbaa710560c0 --- /dev/null +++ b/data/mods/smart_house_remotes/modinfo.json @@ -0,0 +1,13 @@ +[ + { + "type": "MOD_INFO", + "id": "smart_house_remote_mod", + "name": "Smart House Remotes", + "authors": [ "Olanti" ], + "description": "Add remotes for controlling garage doors and window curtains.", + "category": "content", + "obsolete": true, + "lua_api_version": 1, + "dependencies": [ "bn" ] + } +] diff --git a/data/mods/smart_house_remotes/preload.lua b/data/mods/smart_house_remotes/preload.lua new file mode 100644 index 000000000000..ba915e074821 --- /dev/null +++ b/data/mods/smart_house_remotes/preload.lua @@ -0,0 +1,16 @@ +gdebug.log_info("SHR: preload.") + +-- Have to register iuse before data loading. +-- Actual implementation (function mod.iuse_function) will be defined later. + +local mod = game.mod_runtime[ game.current_mod ] + +-- Register our map post-process hook +game.hooks.on_mapgen_postprocess[ #game.hooks.on_mapgen_postprocess + 1 ] = function(...) + return mod.on_mapgen_postprocess_hook(...) +end + +-- Register our item use function +game.iuse_functions[ "SMART_HOUSE_REMOTE" ] = function(...) + return mod.iuse_function(...) +end diff --git a/data/raw/generate_docs.lua b/data/raw/generate_docs.lua new file mode 100644 index 000000000000..58aa5697c406 --- /dev/null +++ b/data/raw/generate_docs.lua @@ -0,0 +1,220 @@ +--[[ + Receives a table and returns sorted array where each value is table of type { k=k, v=v }. + + Sort by key by default, but may also use provided sort function f(a, b) + where a and b - tables of type {k=k, v=v} + (the function must return whether a is less than b). +]]-- +local sorted_by = function(t, f) + if not f then + f = function(a,b) return (a.k < b.k) end + end + local sorted = {} + for k, v in pairs(t) do + sorted[#sorted + 1] = {k=k, v=v} + end + table.sort( sorted, f ) + return sorted +end + +local remove_hidden_args = function(arg_list) + local ret = {} + for _, arg in pairs(arg_list) do + if arg == "" then + -- sol::this_state is only visible to C++ side + else + ret[#ret + 1] = arg + end + end + return ret +end + +local fmt_arg_list = function(arg_list) + local ret = "" + local arg_list = remove_hidden_args(arg_list) + if #arg_list == 0 then + return ret + end + local is_first = true + for _, arg in pairs(arg_list) do + if not is_first then + ret=ret.."," + end + ret=ret.." "..arg + is_first = false + end + return ret.." " +end + +local fmt_one_constructor = function(typename, ctor) + return typename..".new("..fmt_arg_list(ctor)..")" +end + +local fmt_constructors = function(typename, ctors) + if #ctors == 0 then + return " No constructors.\n" + else + local ret = "" + for k,v in pairs(ctors) do + ret=ret.."- `"..fmt_one_constructor(typename, v).."`\n" + end + return ret + end +end + +local fmt_one_member = function(typename, member) + local ret = "#### "..tostring(member.name).."\n"; + + if member.comment then + ret=ret.." // "..member.comment.."\n" + end + + if member.type == "var" then + ret=ret.." Variable of type `"..member.vartype.."`" + if member.hasval then + ret=ret.." value: `"..tostring(member.varval).."`" + end + ret=ret.."\n" + elseif member.type == "func" then + for _,overload in pairs(member.overloads) do + ret=ret.." Function `("..fmt_arg_list(overload.args)..")" + if overload.retval ~= "nil" then + ret=ret.." -> "..overload.retval + end + ret=ret.."`\n" + end + else + error("Unknown member type "..tostring(member.type)) + end + + return ret +end + +local fmt_members = function(typename, members) + if #members == 0 then + return " No members.\n" + else + local ret = "" + + local members_sorted = sorted_by( members ) + + for _,it in pairs(members_sorted) do + ret=ret..fmt_one_member(typename, it.v).."\n" + end + return ret + end +end + +local fmt_bases = function(typename, bases) + if #bases == 0 then + return " No base classes.\n" + else + local ret = "" + for k,v in pairs(bases) do + ret=ret.."- `"..v.."`\n" + end + return ret + end +end + +local fmt_enum_entries = function(typename, entries) + if next(entries) == nil then + return " No entries.\n" + else + local ret = "" + + local entries_filtered = {} + for k,v in pairs(entries) do + -- TODO: this should not be needed + if type(v) ~= "table" and type(v) ~= "function" then + entries_filtered[k] = v; + end + end + + local entries_sorted = sorted_by(entries_filtered, function(a,b) return a.v < b.v end) + for _,it in pairs(entries_sorted) do + ret=ret.."- `"..tostring(it.k).."` = `"..tostring(it.v).."`\n" + end + return ret + end +end + +doc_gen_func.impl = function() + local ret = "# Lua documentation\n\n" + + local dt = catadoc + + ret = ret.."# Types\n\n" + + local types_table = dt["#types"] + + local types_sorted = sorted_by(types_table) + for _,it in pairs(types_sorted) do + local typename = it.k + local dt_type = it.v + local type_comment = dt_type.type_comment + ret = ret.."## "..typename.."\n" + + if type_comment then + ret = ret.."// "..type_comment.."\n" + end + + local bases = dt_type["#bases"] + local ctors = dt_type["#construct"] + local members = dt_type["#member"] + + ret = ret + .."### Bases\n" + ..fmt_bases( typename, bases ) + .."\n" + .."### Constructors\n" + ..fmt_constructors( typename, ctors ) + .."\n" + .."### Members\n" + ..fmt_members( typename, members ) + .."\n" + end + + ret = ret.."# Enums\n\n" + + local enums_table = dt["#enums"] + + local enums_sorted = sorted_by(enums_table) + for _,it in pairs(enums_sorted) do + local typename = it.k + local dt_type = it.v + ret = ret.."## "..typename.."\n" + + local entries = dt_type["entries"] + + ret = ret + .."### Entries\n" + ..fmt_enum_entries( typename, entries ) + .."\n" + end + + ret = ret.."# Libraries\n\n" + + local libs_table = dt["#libs"] + + local libs_sorted = sorted_by( libs_table ) + for _,it in pairs(libs_sorted) do + local typename = it.k + local dt_lib = it.v + local lib_comment = dt_lib.lib_comment + ret = ret.."## "..typename.."\n" + + if lib_comment then + ret = ret.."// "..lib_comment.."\n" + end + + local members = dt_lib["#member"] + + ret = ret + .."### Members\n" + ..fmt_members( nil, members ) + .."\n" + end + + return ret +end diff --git a/data/raw/keybindings/keybindings.json b/data/raw/keybindings/keybindings.json index 59cd9d5a2c67..2dea6a0d65b4 100644 --- a/data/raw/keybindings/keybindings.json +++ b/data/raw/keybindings/keybindings.json @@ -2038,6 +2038,18 @@ "category": "DEFAULTMODE", "id": "debug" }, + { + "type": "keybinding", + "name": "Lua Console", + "category": "DEFAULTMODE", + "id": "lua_console" + }, + { + "type": "keybinding", + "name": "Reload Lua Code", + "category": "DEFAULTMODE", + "id": "lua_reload" + }, { "type": "keybinding", "name": "View Scentmap", @@ -3265,5 +3277,61 @@ "name": "Add new page", "category": "DIARY", "bindings": [ { "input_method": "keyboard", "key": "n" } ] + }, + { + "type": "keybinding", + "id": "EDIT", + "name": "Edit command", + "category": "LUA_CONSOLE", + "bindings": [ { "input_method": "keyboard", "key": "RETURN" } ] + }, + { + "type": "keybinding", + "name": "Reload Lua Code", + "category": "LUA_CONSOLE", + "id": "RELOAD", + "bindings": [ { "input_method": "keyboard", "key": "F4" } ] + }, + { + "type": "keybinding", + "id": "HISTORY_UP", + "name": "History up", + "category": "LUA_CONSOLE", + "bindings": [ { "input_method": "keyboard", "key": "UP" } ] + }, + { + "type": "keybinding", + "id": "HISTORY_DOWN", + "name": "History down", + "category": "LUA_CONSOLE", + "bindings": [ { "input_method": "keyboard", "key": "DOWN" } ] + }, + { + "type": "keybinding", + "id": "SCROLL_UP", + "name": "Scroll up", + "category": "LUA_CONSOLE", + "bindings": [ { "input_method": "keyboard", "key": "PPAGE" } ] + }, + { + "type": "keybinding", + "id": "SCROLL_DOWN", + "name": "Scroll down", + "category": "LUA_CONSOLE", + "bindings": [ { "input_method": "keyboard", "key": "NPAGE" } ] + }, + { + "type": "keybinding", + "id": "SCROLL_TOP", + "name": "Scroll to the top", + "category": "LUA_CONSOLE", + "bindings": [ { "input_method": "keyboard", "key": "HOME" } ] + }, + { + "type": "keybinding", + "id": "SCROLL_BOTTOM", + "name": "Scroll to the bottom", + "category": "LUA_CONSOLE", + "bindings": [ { "input_method": "keyboard", "key": "END" } ] } ] diff --git a/data/raw/on_game_start.lua b/data/raw/on_game_start.lua new file mode 100644 index 000000000000..041496574929 --- /dev/null +++ b/data/raw/on_game_start.lua @@ -0,0 +1 @@ +print('Lua online.') diff --git a/deno.jsonc b/deno.jsonc index 6f78ace93c48..af42dc86124e 100644 --- a/deno.jsonc +++ b/deno.jsonc @@ -1,11 +1,12 @@ { - "tasks": { - "tools": "deno run --watch -A" - }, - "test": { "files": { "include": ["./tools"] } }, - "lint": { "files": { "include": ["./tools"] } }, - "fmt": { - "files": { "include": ["./tools"] }, - "options": { "semiColons": false, "lineWidth": 100 } - } + "tasks": { + "tools": "deno run --watch -A" + }, + "test": { "include": ["./tools"] }, + "lint": { "include": ["./tools"] }, + "fmt": { + "include": ["./tools", "./doc", "*.md"], + "semiColons": false, + "lineWidth": 100 + } } diff --git a/doc/ACCESSIBILITY.md b/doc/ACCESSIBILITY.md index 5a4c511464d8..a3d75e415445 100644 --- a/doc/ACCESSIBILITY.md +++ b/doc/ACCESSIBILITY.md @@ -1,17 +1,15 @@ ### Compatibility with screen readers -There are people who uses screen readers to play Cataclysm DDA. In order for screen -readers to announce the most important information in a UI, the terminal cursor has -to be placed at the correct location. This information may be text such as selected -item names in a list, etc, and the cursor has to be placed exactly at the beginning -of the text for screen readers to announce it. +There are people who uses screen readers to play Cataclysm DDA. In order for screen readers to +announce the most important information in a UI, the terminal cursor has to be placed at the correct +location. This information may be text such as selected item names in a list, etc, and the cursor +has to be placed exactly at the beginning of the text for screen readers to announce it. -`wmove` in `output.h|cpp` is the function to move the cursor to a specific location. -After calling `wmove` with the target `catacurses::window` and cursor position, -`wrefresh` needs to be called immediately afterwards for `wmove` to take effect. +`wmove` in `output.h|cpp` is the function to move the cursor to a specific location. After calling +`wmove` with the target `catacurses::window` and cursor position, `wrefresh` needs to be called +immediately afterwards for `wmove` to take effect. -Here is an example of placing the cursor explicitly at the beginning of a piece -of text: +Here is an example of placing the cursor explicitly at the beginning of a piece of text: ```cpp catacurses::window win = ...; // target window @@ -34,6 +32,5 @@ wrefresh( win ); // no output code should follow as they might change the cursor position ``` -As shown in the above example, it is preferable to record the intended cursor -position in a variable when the text is printed, and move the cursor later using -the variable to ensure consisitency. +As shown in the above example, it is preferable to record the intended cursor position in a variable +when the text is printed, and move the cursor later using the variable to ensure consisitency. diff --git a/doc/BASECAMP.md b/doc/BASECAMP.md index a0fececdc6e2..2b3cbe31c26a 100644 --- a/doc/BASECAMP.md +++ b/doc/BASECAMP.md @@ -1,195 +1,257 @@ # Recommended reading -Basecamps leverage many existing aspects of JSON data such as recipes and mapgen. It's recommended to be familiar with those: -* [JSON info](JSON_INFO.md) has information on common fields for recipes -* [mapgen](MAPGEN.md), see section 3 about `update_mapgen` +Basecamps leverage many existing aspects of JSON data such as recipes and mapgen. It's recommended +to be familiar with those: + +- [JSON info](JSON_INFO.md) has information on common fields for recipes +- [mapgen](MAPGEN.md), see section 3 about `update_mapgen` # Adding alternate basecamp upgrade paths -A basecamp upgrade path is a series of basecamp upgrade missions that upgrade the camp. Upgrade missions are generally performed sequentially, but there is an option to have them branch. Branched missions optionally can have further missions that require missions from other branches. +A basecamp upgrade path is a series of basecamp upgrade missions that upgrade the camp. Upgrade +missions are generally performed sequentially, but there is an option to have them branch. Branched +missions optionally can have further missions that require missions from other branches. Bascamp upgrade paths are defined by several related files: -* The recipe JSONs that define what the material, tool, and skill requirements to perform an upgrade mission and the blueprint mapgen, blueprint requirements, blueprint provides, and blueprint resources associated with each upgrade mission. -* The mapgen_update JSONs that define how the map will change when the upgrade mission is complete. These may include shared instances of nested mapgen, such a standard room or tent. -* The recipe_group JSONs that define what recipes can be crafted after completing the upgrade mission and what camps and expansions are available. + +- The recipe JSONs that define what the material, tool, and skill requirements to perform an upgrade + mission and the blueprint mapgen, blueprint requirements, blueprint provides, and blueprint + resources associated with each upgrade mission. +- The mapgen_update JSONs that define how the map will change when the upgrade mission is complete. + These may include shared instances of nested mapgen, such a standard room or tent. +- The recipe_group JSONs that define what recipes can be crafted after completing the upgrade + mission and what camps and expansions are available. ## recipe JSONs + The recipe JSONs are standard recipe JSONs, with the addition of a few fields. -New field | Description --- | -- -`"construction_blueprint"` | string, the `"update_mapgen_id"` of the mapgen_update JSON that will be performed when the upgrade mission is complete. -`"construction_name"` | string, a short description/name of the upgrade mission that is displayed in the base camp mission selector. The recipe's `"description"` field has the extended description that explains why a player might want to have an NPC perform this upgrade mission. -`"blueprint_provides"` | array of objects, with each object having an `"id"` string and an optional `"amount"` integer. These are the camp features that are available when the upgrade mission is complete. Every upgrade mission provides its recipe `"result"` with an amount of 1 automatically and that string does not need to be listed in `"blueprint_provides"`. -`"blueprint_requires"` | array of objects, with each object having an `"id"` string and an optional `"amount"` integer. These are the camp features that are required before the upgrade mission can be attempted. -`"blueprint_excludes"` | array of objects, with each object having an `"id"` string and an optional `"amount"` integer. These are the camp features that prevent the upgrade mission from being attempted if they exist. -`"blueprint_resources"` | array of `"itype_id"`s. Items with those ids will be added to the camp inventory after the upgrade mission is completed and can be used for crafting or additional upgrade missions. +| New field | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| `"construction_blueprint"` | string, the `"update_mapgen_id"` of the mapgen_update JSON that will be performed when the upgrade mission is complete. | +| `"construction_name"` | string, a short description/name of the upgrade mission that is displayed in the base camp mission selector. The recipe's `"description"` field has the extended description that explains why a player might want to have an NPC perform this upgrade mission. | +| `"blueprint_provides"` | array of objects, with each object having an `"id"` string and an optional `"amount"` integer. These are the camp features that are available when the upgrade mission is complete. Every upgrade mission provides its recipe `"result"` with an amount of 1 automatically and that string does not need to be listed in `"blueprint_provides"`. | +| `"blueprint_requires"` | array of objects, with each object having an `"id"` string and an optional `"amount"` integer. These are the camp features that are required before the upgrade mission can be attempted. | +| `"blueprint_excludes"` | array of objects, with each object having an `"id"` string and an optional `"amount"` integer. These are the camp features that prevent the upgrade mission from being attempted if they exist. | +| `"blueprint_resources"` | array of `"itype_id"`s. Items with those ids will be added to the camp inventory after the upgrade mission is completed and can be used for crafting or additional upgrade missions. | ### blueprint requires, provides, and excludes -blueprint requires, blueprint provides, and blueprint exlcudes are abstract concepts or flags that an upgrade mission requires to start, or that are provided by a previous upgrade mission to satisfy the blueprint requirements of a current upgrade mission, or that prevent an upgrade mission from being available. Each one has an `"id"` and an `"amount"`. Multiple requires, provides, or excludes with the same `"id"` sum their `"amount"` if they're on the same basecamp expansion. - -Every upgrade mission has its recipe `"result"` as a blueprint_provides and a blueprint_excludes, so upgrade missions will automatically prevent themselves from being repeatable. - -These are arbitrary strings and can be used to control the branching of the upgrade paths. However, some strings have meaning within the basecamp code: - -provides `"id"` | meaning --- | -- -`"bed"` | every 2 `"amount"`' of `"bed"` allows another expansion in the camp, to a maximum of 8, not include the camp center. -`"tool_storage"` | after this upgrade mission is complete, the Store Tools mission will be available -. -`"radio"` | after this upgrade mission is complete, two way radios communicating to the camp have extended range. -`"pantry"` | after this upgrade mission is complete, the Distribute Food mission is more efficient when dealing with short term spoilage items. -`"gathering"` | after this upgrade mission is complete, the Gather Materials, Distribute Food, and Reset Sort Points basecamp missions will be available. -`"firewood"` | after this upgrade mission is complete, the Gather Firewood basecamp mission will be available. -`"sorting"` | after this upgrade mission is complete, the Menial Labor basecamp mission will be available. -`"logging"` | after this upgrade mission is complete, the Cut Logs and Clear a Forest basecamp missions will be available. -`"relaying"` | after this upgrade mission is complete, the Setup Hide Site and Relay Hide Site basecamp missions will be available. -`"foraging"` | after this upgrade mission is complete, the Forage for Plants basecamp mission will be available. -`"trapping"` | after this upgrade mission is complete, the Trap Small Game basecamp mission will be available. -`"hunting"` | after this upgrade mission is complete, the Hunt Large Animals basecamp mission will be available. -`"walls"` | after this upgrade mission is complete, the Construct Map Fortifications basecamp mission will be available. -`"recruiting"` | after this upgrade mission is complete, the Recruit Companions basecamp mission will be available. -`"scouting"` | after this upgrade mission is complete, the Scout Mission basecamp mission will be available. -`"patrolling"` | after this upgrade mission is complete, the Combat Patrol basecamp mission will be available. -`"dismantling"` | after this upgrade mission is complete, the Chop Shop basecamp mission will be available. -`"farming"` | after this upgrade mission is complete, the Plow Fields, Plant Fields, Fertilize Fields, and Harvest Fields basecamp missions will be available. - -`blueprint_provides` can also be used to name objects from `recipe_group.json`. The recipes will be craftable by NPCs at that expansion, allowing the creation of custom recipes that can be performed exclusively at faction camps. + +blueprint requires, blueprint provides, and blueprint exlcudes are abstract concepts or flags that +an upgrade mission requires to start, or that are provided by a previous upgrade mission to satisfy +the blueprint requirements of a current upgrade mission, or that prevent an upgrade mission from +being available. Each one has an `"id"` and an `"amount"`. Multiple requires, provides, or excludes +with the same `"id"` sum their `"amount"` if they're on the same basecamp expansion. + +Every upgrade mission has its recipe `"result"` as a blueprint_provides and a blueprint_excludes, so +upgrade missions will automatically prevent themselves from being repeatable. + +These are arbitrary strings and can be used to control the branching of the upgrade paths. However, +some strings have meaning within the basecamp code: + +| provides `"id"` | meaning | +| ---------------- | ------------------------------------------------------------------------------------------------------------------------------------------------ | +| `"bed"` | every 2 `"amount"`' of `"bed"` allows another expansion in the camp, to a maximum of 8, not include the camp center. | +| `"tool_storage"` | after this upgrade mission is complete, the Store Tools mission will be available | +| . | | +| `"radio"` | after this upgrade mission is complete, two way radios communicating to the camp have extended range. | +| `"pantry"` | after this upgrade mission is complete, the Distribute Food mission is more efficient when dealing with short term spoilage items. | +| `"gathering"` | after this upgrade mission is complete, the Gather Materials, Distribute Food, and Reset Sort Points basecamp missions will be available. | +| `"firewood"` | after this upgrade mission is complete, the Gather Firewood basecamp mission will be available. | +| `"sorting"` | after this upgrade mission is complete, the Menial Labor basecamp mission will be available. | +| `"logging"` | after this upgrade mission is complete, the Cut Logs and Clear a Forest basecamp missions will be available. | +| `"relaying"` | after this upgrade mission is complete, the Setup Hide Site and Relay Hide Site basecamp missions will be available. | +| `"foraging"` | after this upgrade mission is complete, the Forage for Plants basecamp mission will be available. | +| `"trapping"` | after this upgrade mission is complete, the Trap Small Game basecamp mission will be available. | +| `"hunting"` | after this upgrade mission is complete, the Hunt Large Animals basecamp mission will be available. | +| `"walls"` | after this upgrade mission is complete, the Construct Map Fortifications basecamp mission will be available. | +| `"recruiting"` | after this upgrade mission is complete, the Recruit Companions basecamp mission will be available. | +| `"scouting"` | after this upgrade mission is complete, the Scout Mission basecamp mission will be available. | +| `"patrolling"` | after this upgrade mission is complete, the Combat Patrol basecamp mission will be available. | +| `"dismantling"` | after this upgrade mission is complete, the Chop Shop basecamp mission will be available. | +| `"farming"` | after this upgrade mission is complete, the Plow Fields, Plant Fields, Fertilize Fields, and Harvest Fields basecamp missions will be available. | + +`blueprint_provides` can also be used to name objects from `recipe_group.json`. The recipes will be +craftable by NPCs at that expansion, allowing the creation of custom recipes that can be performed +exclusively at faction camps. ### Sample recipe JSON + ```JSON - { - "type": "recipe", - "result": "faction_base_camp_8", - "description": "We need to expand our base to include basic dining facilities.", - "category": "CC_BUILDING", - "subcategory": "CSC_BUILDING_BASES", - "skill_used": "fabrication", - "difficulty": 5, - "autolearn": false, - "never_learn": true, - "comment": "2hrs*4wall + .5 hr*2tables + .5hr*4benches+ 1hrs pits = 12 hrs (12hrs on/off) 1 days total", - "time": "1440 m", - "construction_blueprint": "faction_base_field_camp_8", - "blueprint_name": "basic central kitchen", - "blueprint_resources": [ "fake_stove" ], - "blueprint_provides": [ { "id": "trapping", "amount": 1 }, { "id": "hunting", "amount": 1 }, { "id": "walls", "amount": 1 }, { "id": "recruiting", "amount": 1 } - ], - "blueprint_requires": [ { "id": "faction_base_camp_6", "amount": 1 } ], - "qualities": [ [ { "id": "DIG", "level": 1 } ], [ { "id": "SAW_M", "level": 1 } ], [ { "id": "HAMMER", "level": 2 } ] ], - "components": [ [ [ "2x4", 28 ] ], [ [ "log", 16 ] ], [ [ "nail", 56 ] ], [ [ "stick", 24 ] ], [ [ "metal_tank", 1 ] ], [ [ "pipe", 1 ] ] - ] - }, +{ + "type": "recipe", + "result": "faction_base_camp_8", + "description": "We need to expand our base to include basic dining facilities.", + "category": "CC_BUILDING", + "subcategory": "CSC_BUILDING_BASES", + "skill_used": "fabrication", + "difficulty": 5, + "autolearn": false, + "never_learn": true, + "comment": "2hrs*4wall + .5 hr*2tables + .5hr*4benches+ 1hrs pits = 12 hrs (12hrs on/off) 1 days total", + "time": "1440 m", + "construction_blueprint": "faction_base_field_camp_8", + "blueprint_name": "basic central kitchen", + "blueprint_resources": [ "fake_stove" ], + "blueprint_provides": [ { "id": "trapping", "amount": 1 }, { "id": "hunting", "amount": 1 }, { "id": "walls", "amount": 1 }, { "id": "recruiting", "amount": 1 } + ], + "blueprint_requires": [ { "id": "faction_base_camp_6", "amount": 1 } ], + "qualities": [ [ { "id": "DIG", "level": 1 } ], [ { "id": "SAW_M", "level": 1 } ], [ { "id": "HAMMER", "level": 2 } ] ], + "components": [ [ [ "2x4", 28 ] ], [ [ "log", 16 ] ], [ [ "nail", 56 ] ], [ [ "stick", 24 ] ], [ [ "metal_tank", 1 ] ], [ [ "pipe", 1 ] ] + ] +}, ``` -The `"faction_base_camp_8"` upgrade mission can be performed after `"faction_base_camp_6"` and enables the trapping, hunting, fortification, and recruiting basecamp missions. It adds a camp stove to the camp's inventory to represent the iron stove. +The `"faction_base_camp_8"` upgrade mission can be performed after `"faction_base_camp_6"` and +enables the trapping, hunting, fortification, and recruiting basecamp missions. It adds a camp stove +to the camp's inventory to represent the iron stove. -`"blueprint_autocalc": true` could be used instead of `components` to let the cost be calculated automatically from the mapgen\_update data. +`"blueprint_autocalc": true` could be used instead of `components` to let the cost be calculated +automatically from the mapgen\_update data. ## mapgen_update JSON -These are standard mapgen_update JSON; see doc/MAPGEN.md for more details. Each one should change a localized portion of the camp map and should, as much as possible, be independent of any other pieces of mapgen_update for the basecamp upgrade path. Obviously, some bits are going to expand other bits, in which case their `"blueprint_requires"` should include the `"blueprint_provides"` of the previous upgrade missions. +These are standard mapgen_update JSON; see doc/MAPGEN.md for more details. Each one should change a +localized portion of the camp map and should, as much as possible, be independent of any other +pieces of mapgen_update for the basecamp upgrade path. Obviously, some bits are going to expand +other bits, in which case their `"blueprint_requires"` should include the `"blueprint_provides"` of +the previous upgrade missions. ### Sample mapgen_update JSON ```json - { - "type": "mapgen", - "update_mapgen_id": "faction_base_field_camp_7", - "method": "json", - "object": { "place_nested": [ { "chunks": [ "basecamp_large_tent_east" ], "x": 2, "y": 10 } ] } - }, - { - "type": "mapgen", - "method": "json", - "nested_mapgen_id": "basecamp_large_tent_east", - "object": { - "mapgensize": [ 5, 5 ], - "rows": [ - "WWWWW", - "Wbb$W", - "Wr;;D", - "Wbb$W", - "WWWWW" - ], - "palettes": [ "acidia_camp_palette" ] - } - }, +{ + "type": "mapgen", + "update_mapgen_id": "faction_base_field_camp_7", + "method": "json", + "object": { "place_nested": [ { "chunks": [ "basecamp_large_tent_east" ], "x": 2, "y": 10 } ] } +}, +{ + "type": "mapgen", + "method": "json", + "nested_mapgen_id": "basecamp_large_tent_east", + "object": { + "mapgensize": [ 5, 5 ], + "rows": [ + "WWWWW", + "Wbb$W", + "Wr;;D", + "Wbb$W", + "WWWWW" + ], + "palettes": [ "acidia_camp_palette" ] + } +}, ``` -This mapgen_update places a large tent in the west central portion of the camp. The `"place_nested"` references a standard map used in the primitive field camp. +This mapgen_update places a large tent in the west central portion of the camp. The `"place_nested"` +references a standard map used in the primitive field camp. ## Recipe groups -Recipe groups serve two purposes: they indicate what recipes can produced by the camp after an upgrade mission is completed, and they indicate what upgrade paths are available and where camps can be placed. + +Recipe groups serve two purposes: they indicate what recipes can produced by the camp after an +upgrade mission is completed, and they indicate what upgrade paths are available and where camps can +be placed. ### Upgrade Paths and Expansions -There are two special recipe groups, `"all_faction_base_types"` and `"all_faction_base_expansions"`. They both look like this: + +There are two special recipe groups, `"all_faction_base_types"` and `"all_faction_base_expansions"`. +They both look like this: + ```json - { - "type": "recipe_group", - "name": "all_faction_base_expansions", - "building_type": "NONE", - "recipes": [ - { "id": "faction_base_farm_0", "description": "Farm", "om_terrains": [ "field" ] }, - { "id": "faction_base_garage_0", "description": "Garage", "om_terrains": [ "field" ] }, - { "id": "faction_base_kitchen_0", "description": "Kitchen", "om_terrains": [ "field" ] }, - { "id": "faction_base_blacksmith_0", "description": "Blacksmith Shop", "om_terrains": [ "field" ] } - ] - }, +{ + "type": "recipe_group", + "name": "all_faction_base_expansions", + "building_type": "NONE", + "recipes": [ + { "id": "faction_base_farm_0", "description": "Farm", "om_terrains": [ "field" ] }, + { "id": "faction_base_garage_0", "description": "Garage", "om_terrains": [ "field" ] }, + { "id": "faction_base_kitchen_0", "description": "Kitchen", "om_terrains": [ "field" ] }, + { "id": "faction_base_blacksmith_0", "description": "Blacksmith Shop", "om_terrains": [ "field" ] } + ] +}, ``` -Each entry in the `"recipes"` array must be a dictionary with the `"id"`, `"description"`, and `"om_terrains"` fields. `"id"` is the recipe `"id"` of the recipe that starts that basecamp or basecamp expansion upgrade path. `"description"` is a short name of the basecamp or basecamp expansion. `"om_terrains"` is a list of overmap terrain ids which can be used as the basis for the basecamp or basecamp expansion. +Each entry in the `"recipes"` array must be a dictionary with the `"id"`, `"description"`, and +`"om_terrains"` fields. `"id"` is the recipe `"id"` of the recipe that starts that basecamp or +basecamp expansion upgrade path. `"description"` is a short name of the basecamp or basecamp +expansion. `"om_terrains"` is a list of overmap terrain ids which can be used as the basis for the +basecamp or basecamp expansion. -All recipes that start an upgrade path or expansion should have a blueprint requirement that can never be met, such as "not_an_upgrade", to prevent them from showing up as available upgrades. +All recipes that start an upgrade path or expansion should have a blueprint requirement that can +never be met, such as "not_an_upgrade", to prevent them from showing up as available upgrades. -If the player attempts to start a basecamp on an overmap terrain that has two or more valid basecamp expansion paths, she will allowed to choose which path to start. +If the player attempts to start a basecamp on an overmap terrain that has two or more valid basecamp +expansion paths, she will allowed to choose which path to start. ## Sample basecamp upgrade path The primitive field camp has the following upgrade path: + 1. `"faction_base_camp_0"` - the initial camp survey and the bulletin board. 2. `"faction_base_camp_1"` - setting up the northeast tent 3. `"faction_base_camp_2"` - digging the fire pit and constructing a bed 4. `"faction_base_camp_3"` - adding the bookshelves to store stuff 5. `"faction_base_camp_4"` - adding the second bed to the tent -6. any of: -`"faction_base_camp_5"`, `"faction_base_camp_7"`, `"faction_base_camp_9"`, `"faction_base_camp_15"`, `"faction_base_camp_18"` - add additional tents with beds in any order. -or `"faction_base_camp_6"` - build the central kitchen. `"faction_base_camp_8"`, `"faction_base_camp_10"`, `"faction_base_camp_11"`, `"faction_base_camp_16"` must be built in that sequence afterwards, though interleaved with the other optional upgrade missions after `"faction_base_camp_4"`. -or `"faction_base_camp_12"` - the central camp well. -or `"faction_base_camp_13"` - building the camp's outer wall, which can be followed by `"faction_base_camp_14"` to complete the wall. -or `"faction_base_camp_19"` - building the camp's radio tower, which can be followed by `"faction_base_camp_20"` to build the radio tower console and make it operational. -7. `"faction_base_camp_17"` - adding better doors to camp wall and the central building must be built after `"faction_base_camp_14"` and `"faction_base_camp_16"`. - -After setting up the first tent, the player has a lot of options: they can build additional tents to enable expansions, they can build the well for water, they can build as much or as little of the central kitchen as they desire, or add the wall to give the camp defenses, or the radio tower to improve the range of their two-way radios. +6. any of: `"faction_base_camp_5"`, `"faction_base_camp_7"`, `"faction_base_camp_9"`, + `"faction_base_camp_15"`, `"faction_base_camp_18"` - add additional tents with beds in any order. + or `"faction_base_camp_6"` - build the central kitchen. `"faction_base_camp_8"`, + `"faction_base_camp_10"`, `"faction_base_camp_11"`, `"faction_base_camp_16"` must be built in + that sequence afterwards, though interleaved with the other optional upgrade missions after + `"faction_base_camp_4"`. or `"faction_base_camp_12"` - the central camp well. or + `"faction_base_camp_13"` - building the camp's outer wall, which can be followed by + `"faction_base_camp_14"` to complete the wall. or `"faction_base_camp_19"` - building the camp's + radio tower, which can be followed by `"faction_base_camp_20"` to build the radio tower console + and make it operational. +7. `"faction_base_camp_17"` - adding better doors to camp wall and the central building must be + built after `"faction_base_camp_14"` and `"faction_base_camp_16"`. + +After setting up the first tent, the player has a lot of options: they can build additional tents to +enable expansions, they can build the well for water, they can build as much or as little of the +central kitchen as they desire, or add the wall to give the camp defenses, or the radio tower to +improve the range of their two-way radios. ## Modular Basecamp conventions -The modular basecamp is a structure for designing basecamp upgrade paths. You don't have to use it, but elements of the design might get more code support in the future. + +The modular basecamp is a structure for designing basecamp upgrade paths. You don't have to use it, +but elements of the design might get more code support in the future. ### Layout -A modular camp is laid out on a 24x24 overmap tile. The outer 3 map squares on each side are reserved for fortifications and movement corridors, and the inner 18x18 map squares are divided into a 3x3 grid of 6x6 areas. - -Area | upper left position | lower right position --- | -- | -- -northwest | 3, 3 | 8, 8 -north | 9, 3 | 14, 8 -northeast | 15, 3 | 20, 8 -west | 3, 9 | 8, 14 -center | 9, 9 | 14, 14 -east | 15, 9, | 20, 14 -southwest | 3, 15 | 8, 20 -south | 9, 15 | 14, 20 -southeast | 15, 15 | 20, 20 + +A modular camp is laid out on a 24x24 overmap tile. The outer 3 map squares on each side are +reserved for fortifications and movement corridors, and the inner 18x18 map squares are divided into +a 3x3 grid of 6x6 areas. + +| Area | upper left position | lower right position | +| --------- | ------------------- | -------------------- | +| northwest | 3, 3 | 8, 8 | +| north | 9, 3 | 14, 8 | +| northeast | 15, 3 | 20, 8 | +| west | 3, 9 | 8, 14 | +| center | 9, 9 | 14, 14 | +| east | 15, 9, | 20, 14 | +| southwest | 3, 15 | 8, 20 | +| south | 9, 15 | 14, 20 | +| southeast | 15, 15 | 20, 20 | Ideally, nested mapgen chunks should fit entirely into a 6x6 area. ### Naming scheme -Modular bases use the following naming scheme for recipes. Each element is separated by an `_` - -* `"faction_base"` <-- encouraged for all basecamp recipes, _and_ -* `"modular"` <-- indicates a modular construction, _and_ -* overmap terrain id <-- the base terrain that this modular base is built upon, _and_ -* DESCRIPTOR <-- arbitrary string that describes what is being built. For buildings, "room" is used to mean a construction that is intended to be part of a larger building and might share walls with other parts of the building in adjacent areas; "shack" means a free standing building. Numbers indicate stages of construction, with 4 usually meaning a complete structure, with walls and roof, _and_ -* MATERIAL <-- the type of material used in construction, such as metal, wood, brick, or wad (short for wattle-and-daub), _and_ -* AREA <-- the area in the 3x3 grid of the modular camp layout. -blueprint keywords follow a similar scheme, but `"faction_base_modular"` is collapsed into `"fbm"` and the overmap terrain id is collapsed into a short identifier. ie, `"fbmf"` is the keyword identifier for elements of the modular field base. +Modular bases use the following naming scheme for recipes. Each element is separated by an `_` + +- `"faction_base"` <-- encouraged for all basecamp recipes, _and_ +- `"modular"` <-- indicates a modular construction, _and_ +- overmap terrain id <-- the base terrain that this modular base is built upon, _and_ +- DESCRIPTOR <-- arbitrary string that describes what is being built. For buildings, "room" is used + to mean a construction that is intended to be part of a larger building and might share walls with + other parts of the building in adjacent areas; "shack" means a free standing building. Numbers + indicate stages of construction, with 4 usually meaning a complete structure, with walls and roof, + _and_ +- MATERIAL <-- the type of material used in construction, such as metal, wood, brick, or wad (short + for wattle-and-daub), _and_ +- AREA <-- the area in the 3x3 grid of the modular camp layout. + +blueprint keywords follow a similar scheme, but `"faction_base_modular"` is collapsed into `"fbm"` +and the overmap terrain id is collapsed into a short identifier. ie, `"fbmf"` is the keyword +identifier for elements of the modular field base. diff --git a/doc/CHANGELOG_GUIDELINES.md b/doc/CHANGELOG_GUIDELINES.md index a88828ee2624..153791c55438 100644 --- a/doc/CHANGELOG_GUIDELINES.md +++ b/doc/CHANGELOG_GUIDELINES.md @@ -1,38 +1,39 @@ # Changelog Guidelines -- categories used by `Pull Request Summary` in the [PR Template](../.github/pull_request_template.md). -- these are only guidelines, not rules. choose the best category for your PR freely. +- categories used by `Pull Request Summary` in the + [PR Template](../.github/pull_request_template.md). +- these are only guidelines, not rules. choose the best category for your PR freely. ## Features Changes related to player: -- player can do something new (e.g: mutations, skills) -- something new can happen to the player (e.g: new disease) +- player can do something new (e.g: mutations, skills) +- something new can happen to the player (e.g: new disease) ## Content Added new contents like: -- new monsters -- new map areas -- new items -- new vehicles -- new doohickeys +- new monsters +- new map areas +- new items +- new vehicles +- new doohickeys ## Interface UI/UX changes like: -- adding/adjusting menus -- change shortcuts -- streamlining workflows -- quality of life improvements +- adding/adjusting menus +- change shortcuts +- streamlining workflows +- quality of life improvements ## Mods -- changes contained within a mod -- extends what is capable within a mod +- changes contained within a mod +- extends what is capable within a mod ## Balance @@ -50,18 +51,18 @@ Improvements to game performance. Make development easier: -- `C++` refactorings and overhaul -- `Json` reorganizations -- `docs/`, `.github/` and repository changes -- other development tools +- `C++` refactorings and overhaul +- `Json` reorganizations +- `docs/`, `.github/` and repository changes +- other development tools ## Build Improve build process: -- more robust -- easier to use -- faster compile time +- more robust +- easier to use +- faster compile time ## I18N diff --git a/doc/CODE_STYLE.md b/doc/CODE_STYLE.md index a9678abf60b6..b871a759a1d9 100644 --- a/doc/CODE_STYLE.md +++ b/doc/CODE_STYLE.md @@ -1,14 +1,17 @@ # Code Style Guide -All of the C++ code in the project is styled, you should run any changes you make through astyle before pushing a pull request. +All of the C++ code in the project is styled, you should run any changes you make through astyle +before pushing a pull request. -We are using astyle version 3.0.1. Version 3.1 should also work, though there are a few cases where they disagree and require annotation. +We are using astyle version 3.0.1. Version 3.1 should also work, though there are a few cases where +they disagree and require annotation. Blocks of code can be passed through astyle to ensure that their formatting is correct: astyle --style=1tbs --attach-inlines --indent=spaces=4 --align-pointer=name --max-code-length=100 --break-after-logical --indent-classes --indent-preprocessor --indent-switches --indent-col1-comments --min-conditional-indent=0 --pad-oper --unpad-paren --pad-paren-in --add-brackets --convert-tabs -These options are mirrored in `.astylerc`, `doc/CODE_STYLE.txt` and `msvc-full-features/AStyleExtension-Cataclysm-BN.cfg` +These options are mirrored in `.astylerc`, `doc/CODE_STYLE.txt` and +`msvc-full-features/AStyleExtension-Cataclysm-BN.cfg` For example, from `vi`, set marks a and b around the block, then: @@ -20,7 +23,7 @@ See [DEVELOPER_TOOLING.md](DEVELOPER_TOOLING.md) for other environments. Here's an example that illustrates the most common points of style: -````c++ +```c++ int foo( int arg1, int *arg2 ) { if( arg1 < 5 ) { @@ -44,19 +47,22 @@ int foo( int arg1, int *arg2 ) } return 0; } -```` +``` ## Code Guidelines These are less generic guidelines and more pain points we've stumbled across over time. 1. Use int for everything. - 1. Long in particular is problematic since it is *not* a larger type than int on platforms we care about. - 1. If you need an integral value larger than 32 bits, you don't. But if you do, use int64_t. - 2. Uint is also a problem, it has poor behavior when overflowing and should be avoided for general purpose programming. - 1. If you need binary data, unsigned int or unsigned char are fine, but you should probably use a std::bitset instead. - 3. Float is to be avoided, but has valid uses. + 1. Long in particular is problematic since it is _not_ a larger type than int on platforms we + care about. + 1. If you need an integral value larger than 32 bits, you don't. But if you do, use int64_t. + 2. Uint is also a problem, it has poor behavior when overflowing and should be avoided for + general purpose programming. + 1. If you need binary data, unsigned int or unsigned char are fine, but you should probably + use a std::bitset instead. + 3. Float is to be avoided, but has valid uses. 2. Auto Almost Nothing. Auto has two uses, others should be avoided. - 1. Aliasing for extremely long iterator or functional declarations. - 2. Generic code support (but decltype is better). + 1. Aliasing for extremely long iterator or functional declarations. + 2. Generic code support (but decltype is better). 3. Avoid using declaration for standard namespaces. diff --git a/doc/COLOR.md b/doc/COLOR.md index 4babaf72cd25..442414a9f2ee 100644 --- a/doc/COLOR.md +++ b/doc/COLOR.md @@ -2,40 +2,48 @@ DDA is colorful game. You can use several foreground and background colors in various places: -* map data (terrain and furniture); -* item data; -* text data; -* etc. +- map data (terrain and furniture); +- item data; +- text data; +- etc. -**Note:** Map data objects can only have one color-related node defined (either `color` or `bgcolor`). +**Note:** Map data objects can only have one color-related node defined (either `color` or +`bgcolor`). ## Color string format -Whenever color is defined in JSON it should be defined in following format: `Prefix_Foreground_Background`. +Whenever color is defined in JSON it should be defined in following format: +`Prefix_Foreground_Background`. `Prefix` can take one of following values: -* `c_` - default color prefix (can be omitted); -* `i_` - optional prefix which indicates that foreground color should be inverted (special rules will be applied to foreground and background colors); -* `h_` - optional prefix which indicates that foreground color should be highlighted (special rules will be applied to foreground and background colors). +- `c_` - default color prefix (can be omitted); +- `i_` - optional prefix which indicates that foreground color should be inverted (special rules + will be applied to foreground and background colors); +- `h_` - optional prefix which indicates that foreground color should be highlighted (special rules + will be applied to foreground and background colors). `Foreground` - defines mandatory color of foreground/ink/font. `Background` - defines optional color of background/paper. -**Note:** Not all foreground + background pairs are defined by their full name. Use in-game Color manager to see all color names. +**Note:** Not all foreground + background pairs are defined by their full name. Use in-game Color +manager to see all color names. -**Note:** If color was not found by its name, then `c_unset` is used for `Foreground` and `i_white` for `Background`. +**Note:** If color was not found by its name, then `c_unset` is used for `Foreground` and `i_white` +for `Background`. ## Examples of color strings - `c_white` - `white` color (with default prefix `c_`); -- `black` - `black` color (default prefix `c_` is omitted); +- `black` - `black` color (default prefix `c_` is omitted); - `i_red` - inverted `red` color; - `dark_gray_white` - `dark_gray` foreground color with `white` background color; - `light_gray_light_red` - `light_gray` foreground color with `light_red` background color; -- `dkgray_red` - `dark_gray` foreground color with `red` background color (deprecated prefix `dk` instead of `dark_`); -- `ltblue_red` - `light_blue` foreground color with `red` background color (deprecated prefix `lt` instead of `light_`). +- `dkgray_red` - `dark_gray` foreground color with `red` background color (deprecated prefix `dk` + instead of `dark_`); +- `ltblue_red` - `light_blue` foreground color with `red` background color (deprecated prefix `lt` + instead of `light_`). ## Color code @@ -43,33 +51,35 @@ Color code is short string which defines color and can be used, for example, in ## Possible colors -| Color (image) | Color name (dda) | Color name (curses) | Default R,G,B values | Color code | Notes | -|:--------------------------------------------------------:|:------------------:|:-------------------:|:--------------------:|:----------:|:------------------------------------------------------:| -| ![#000000](https://placehold.it/20/000000/000000?text=+) | `black` | `BLACK` | `0,0,0` | | | -| ![#ff0000](https://placehold.it/20/ff0000/000000?text=+) | `red` | `RED` | `255,0,0` | `R` | | -| ![#006e00](https://placehold.it/20/006e00/000000?text=+) | `green` | `GREEN` | `0,110,0` | `G` | | -| ![#5c3317](https://placehold.it/20/5c3317/000000?text=+) | `brown` | `BROWN` | `92,51,23` | `br` | | -| ![#0000c8](https://placehold.it/20/0000c8/000000?text=+) | `blue` | `BLUE` | `0,0,200` | `B` | | -| ![#8b3a62](https://placehold.it/20/8b3a62/000000?text=+) | `magenta` or `pink`| `MAGENTA` | `139,58,98` | `P` | | -| ![#0096b4](https://placehold.it/20/0096b4/000000?text=+) | `cyan` | `CYAN` | `0,150,180` | `C` | | -| ![#969696](https://placehold.it/20/969696/000000?text=+) | `light_gray` | `GRAY` | `150,150,150` | `lg` | deprecated `lt` prefix can be used instead of `light_` | -| ![#636363](https://placehold.it/20/636363/000000?text=+) | `dark_gray` | `DGRAY` | `99,99,99` | `dg` | deprecated `dk` prefix can be used instead of `dark_` | -| ![#ff9696](https://placehold.it/20/ff9696/000000?text=+) | `light_red` | `LRED` | `255,150,150` | | deprecated `lt` prefix can be used instead of `light_` | -| ![#00ff00](https://placehold.it/20/00ff00/000000?text=+) | `light_green` | `LGREEN` | `0,255,0` | `g` | deprecated `lt` prefix can be used instead of `light_` | -| ![#ffff00](https://placehold.it/20/ffff00/000000?text=+) | `light_yellow` | `YELLOW` | `255,255,0` | | deprecated `lt` prefix can be used instead of `light_` | -| ![#6464ff](https://placehold.it/20/6464ff/000000?text=+) | `light_blue` | `LBLUE` | `100,100,255` | `b` | deprecated `lt` prefix can be used instead of `light_` | -| ![#fe00fe](https://placehold.it/20/fe00fe/000000?text=+) | `light_magenta` | `LMAGENTA` | `254,0,254` | `lm` | deprecated `lt` prefix can be used instead of `light_` | -| ![#00f0ff](https://placehold.it/20/00f0ff/000000?text=+) | `light_cyan` | `LCYAN` | `0,240,255` | `c` | deprecated `lt` prefix can be used instead of `light_` | -| ![#ffffff](https://placehold.it/20/ffffff/000000?text=+) | `white` | `WHITE` | `255,255,255` | `W` | | - -**Note:** Default RGB values are taken from file `\data\raw\colors.json`. -**Note:** RGB values can be redefined in file `\config\base_colors.json`. +| Color (image) | Color name (dda) | Color name (curses) | Default R,G,B values | Color code | Notes | +| :------------------------------------------------------: | :-----------------: | :-----------------: | :------------------: | :--------: | :----------------------------------------------------: | +| ![#000000](https://placehold.it/20/000000/000000?text=+) | `black` | `BLACK` | `0,0,0` | | | +| ![#ff0000](https://placehold.it/20/ff0000/000000?text=+) | `red` | `RED` | `255,0,0` | `R` | | +| ![#006e00](https://placehold.it/20/006e00/000000?text=+) | `green` | `GREEN` | `0,110,0` | `G` | | +| ![#5c3317](https://placehold.it/20/5c3317/000000?text=+) | `brown` | `BROWN` | `92,51,23` | `br` | | +| ![#0000c8](https://placehold.it/20/0000c8/000000?text=+) | `blue` | `BLUE` | `0,0,200` | `B` | | +| ![#8b3a62](https://placehold.it/20/8b3a62/000000?text=+) | `magenta` or `pink` | `MAGENTA` | `139,58,98` | `P` | | +| ![#0096b4](https://placehold.it/20/0096b4/000000?text=+) | `cyan` | `CYAN` | `0,150,180` | `C` | | +| ![#969696](https://placehold.it/20/969696/000000?text=+) | `light_gray` | `GRAY` | `150,150,150` | `lg` | deprecated `lt` prefix can be used instead of `light_` | +| ![#636363](https://placehold.it/20/636363/000000?text=+) | `dark_gray` | `DGRAY` | `99,99,99` | `dg` | deprecated `dk` prefix can be used instead of `dark_` | +| ![#ff9696](https://placehold.it/20/ff9696/000000?text=+) | `light_red` | `LRED` | `255,150,150` | | deprecated `lt` prefix can be used instead of `light_` | +| ![#00ff00](https://placehold.it/20/00ff00/000000?text=+) | `light_green` | `LGREEN` | `0,255,0` | `g` | deprecated `lt` prefix can be used instead of `light_` | +| ![#ffff00](https://placehold.it/20/ffff00/000000?text=+) | `light_yellow` | `YELLOW` | `255,255,0` | | deprecated `lt` prefix can be used instead of `light_` | +| ![#6464ff](https://placehold.it/20/6464ff/000000?text=+) | `light_blue` | `LBLUE` | `100,100,255` | `b` | deprecated `lt` prefix can be used instead of `light_` | +| ![#fe00fe](https://placehold.it/20/fe00fe/000000?text=+) | `light_magenta` | `LMAGENTA` | `254,0,254` | `lm` | deprecated `lt` prefix can be used instead of `light_` | +| ![#00f0ff](https://placehold.it/20/00f0ff/000000?text=+) | `light_cyan` | `LCYAN` | `0,240,255` | `c` | deprecated `lt` prefix can be used instead of `light_` | +| ![#ffffff](https://placehold.it/20/ffffff/000000?text=+) | `white` | `WHITE` | `255,255,255` | `W` | | + +**Note:** Default RGB values are taken from file `\data\raw\colors.json`. **Note:** RGB values can +be redefined in file `\config\base_colors.json`. ## Color rules -There are two types of special color transformation which can affect both foreground and background color: +There are two types of special color transformation which can affect both foreground and background +color: -* inversion; -* highlight. +- inversion; +- highlight. -**Note:** Color rules can be redefined (for example, `\data\raw\color_templates\no_bright_background.json`). +**Note:** Color rules can be redefined (for example, +`\data\raw\color_templates\no_bright_background.json`). diff --git a/doc/COMPILING/COMPILER_SUPPORT.md b/doc/COMPILING/COMPILER_SUPPORT.md index 22e1f79df182..8c9d8a3bf4e8 100644 --- a/doc/COMPILING/COMPILER_SUPPORT.md +++ b/doc/COMPILING/COMPILER_SUPPORT.md @@ -1,20 +1,18 @@ # Compilers Supported -Our goal with compiler support is to make it as easy as possible for new -contributors to get started with development of the game, while also using the -newest compilers (and thus language standards) that we can. +Our goal with compiler support is to make it as easy as possible for new contributors to get started +with development of the game, while also using the newest compilers (and thus language standards) +that we can. -To that end, we aim to support gcc and clang up to the newest stable versions -and back to those shipping in any supported version of a popular distribution -or relevant development environment, including Ubuntu, Debian, MSYS, and XCode. +To that end, we aim to support gcc and clang up to the newest stable versions and back to those +shipping in any supported version of a popular distribution or relevant development environment, +including Ubuntu, Debian, MSYS, and XCode. -In practice, compiler support is often determined by what is covered in our -automated testing. +In practice, compiler support is often determined by what is covered in our automated testing. -At time of writing, the oldest relevant compiler is gcc 5.3, shipped in the -Ubuntu Xenial LTS release. Ubuntu is likely to remain the limiting factor, so -the set of supported compilers should be reviewed when Xenial ceases support in -2021-05. +At time of writing, the oldest relevant compiler is gcc 5.3, shipped in the Ubuntu Xenial LTS +release. Ubuntu is likely to remain the limiting factor, so the set of supported compilers should be +reviewed when Xenial ceases support in 2021-05. ## GCC @@ -26,16 +24,16 @@ We support and test Clang from version 14. ## Mingw and Mingw-w64 -We use Mingw for cross-compilation of Windows versions on Linux. gcc 5.4 is -currently used both in the tests and for the Windows release binaries. +We use Mingw for cross-compilation of Windows versions on Linux. gcc 5.4 is currently used both in +the tests and for the Windows release binaries. ## MSYS2 -MSYS2 is [a way to build the project](COMPILING-MSYS.md) on Windows. It -currently offers gcc at versions 7 or higher. +MSYS2 is [a way to build the project](COMPILING-MSYS.md) on Windows. It currently offers gcc at +versions 7 or higher. -MSYS also provides clang. We don't currently support using clang here, but -work to that end is welcome. +MSYS also provides clang. We don't currently support using clang here, but work to that end is +welcome. ## Visual Studio diff --git a/doc/COMPILING/COMPILING-CMAKE.md b/doc/COMPILING/COMPILING-CMAKE.md index 9759e51734ed..cb6c9e26d08a 100644 --- a/doc/COMPILING/COMPILING-CMAKE.md +++ b/doc/COMPILING/COMPILING-CMAKE.md @@ -1,333 +1,354 @@ # Disclaimer -**WARNING**: CMake build is **NOT** official and should be used for *dev purposes ONLY*. +**WARNING**: CMake build is **NOT** official and should be used for _dev purposes ONLY_. For official way to build CataclysmBN See: - * [COMPILING.md](COMPILING.md) +- [COMPILING.md](COMPILING.md) # Contents - * [Prerequisites](#prerequisites) - * [Build Environment](#build-environment) - * [UNIX Environment](#unix-environment) - * [Windows Environment](#windows-environment-msys2) - * [CMake Build](#cmake-build) - * [MinGW,MSYS,MSYS2](#cmake-build-for-msys2-mingw) - * [MSBuild, VisualStudio](#cmake-build-for-visual-studio--msbuild) - * [Build Options](#build-options) - * [CMake specific options](#cmake-specific-options) - * [CataclysmBN specific options])(#cataclysmbn-specific-options) - # Prerequisites -You'll need to have these libraries and their development headers installed in -order to build CataclysmBN: - - * General - * `cmake` >= 3.0.0 - * `gcc-libs` - * `glibc` - * `zlib` - * `bzip2` - * Curses - * `ncurses` - * Tiles - * `SDL` >= 2.0.0 - * `SDL_image` >= 2.0.0 (with PNG and JPEG support) - * `SDL_mixer` >= 2.0.0 (with Ogg Vorbis support) - * `SDL_ttf` >= 2.0.0 - * `freetype` - * Sound - * `vorbis` - * `libbz2` - * `libz` +You'll need to have these libraries and their development headers installed in order to build +CataclysmBN: + +- General + - `cmake` >= 3.0.0 + - `gcc-libs` + - `glibc` + - `zlib` + - `bzip2` +- Curses + - `ncurses` +- Tiles + - `SDL` >= 2.0.0 + - `SDL_image` >= 2.0.0 (with PNG and JPEG support) + - `SDL_mixer` >= 2.0.0 (with Ogg Vorbis support) + - `SDL_ttf` >= 2.0.0 + - `freetype` +- Sound + - `vorbis` + - `libbz2` + - `libz` In order to compile localization files, you'll also need `gettext` package. # Build Environment -You can obtain the source code tarball for the latest version from [git](https://github.com/cataclysmbnteam/Cataclysm-BN). - +You can obtain the source code tarball for the latest version from +[git](https://github.com/cataclysmbnteam/Cataclysm-BN). ## UNIX Environment Obtain packages specified above with your system package manager. - ## Windows Environment (MSYS2) - 1. Follow steps from here: https://msys2.github.io/ - 2. Install CataclysmBN build deps: - - ``` - pacman -S mingw-w64-i686-toolchain msys/git \ - mingw-w64-i686-cmake \ - mingw-w64-i686-SDL2_{image,mixer,ttf} \ - ncurses-devel \ - gettext - ``` +1. Follow steps from here: https://msys2.github.io/ +2. Install CataclysmBN build deps: - This should get your environment set up to build console and tiles version of windows. +``` +pacman -S mingw-w64-i686-toolchain msys/git \ + mingw-w64-i686-cmake \ + mingw-w64-i686-SDL2_{image,mixer,ttf} \ + ncurses-devel \ + gettext +``` - **NOTE**: This is only for 32bit builds. 64bit requires the x86_64 instead of the i686 - packages listed above: +This should get your environment set up to build console and tiles version of windows. - ``` - pacman -S mingw-w64-x86_64-toolchain msys/git \ - mingw-w64-x86_64-cmake \ - mingw-w64-x86_64-SDL2_{image,mixer,ttf} \ - ncurses-devel \ - gettext - ``` +**NOTE**: This is only for 32bit builds. 64bit requires the x86_64 instead of the i686 packages +listed above: - **NOTE**: If you're trying to test with Jetbrains CLion, point to the cmake version in the - msys32/mingw32 path instead of using the built in. This will let cmake detect the - installed packages. +``` +pacman -S mingw-w64-x86_64-toolchain msys/git \ + mingw-w64-x86_64-cmake \ + mingw-w64-x86_64-SDL2_{image,mixer,ttf} \ + ncurses-devel \ + gettext +``` +**NOTE**: If you're trying to test with Jetbrains CLion, point to the cmake version in the +msys32/mingw32 path instead of using the built in. This will let cmake detect the installed +packages. # CMake Build - CMake has separate configuration and build steps. Configuration - is done using CMake itself, and the actual build is done using either `make` - (for Makefiles generator) or build-system agnostic `cmake --build . ` . - - There are two ways to build CataclysmBN with CMake: inside the source tree or - outside of it. Out-of-source builds have the advantage that you can have - multiple builds with different options from one source directory. +CMake has separate configuration and build steps. Configuration is done using CMake itself, and the +actual build is done using either `make` (for Makefiles generator) or build-system agnostic +`cmake --build .` . - **WARNING**: Inside the source tree build is **NOT** supported. +There are two ways to build CataclysmBN with CMake: inside the source tree or outside of it. +Out-of-source builds have the advantage that you can have multiple builds with different options +from one source directory. - To build CataclysmBN out of source: +**WARNING**: Inside the source tree build is **NOT** supported. - ``` - $ mkdir build && cd build - $ cmake .. -DCMAKE_BUILD_TYPE=Release - $ make - ``` +To build CataclysmBN out of source: -The above example creates a build directory inside the source directory, but that's not required - you can just as easily create it in a completely different location. +``` +$ mkdir build && cd build + $ cmake .. -DCMAKE_BUILD_TYPE=Release + $ make +``` - To install CataclysmBN after building (as root using su or sudo if necessary): +The above example creates a build directory inside the source directory, but that's not required - +you can just as easily create it in a completely different location. - ``` - # make install - ``` +To install CataclysmBN after building (as root using su or sudo if necessary): - To change build options, you can either pass the options on the command line: +``` +# make install +``` - ``` - $ cmake .. -DOPTION_NAME=option_value - ``` +To change build options, you can either pass the options on the command line: - Or use either the `ccmake` or `cmake-gui` front-ends, which display all options - and their cached values on a console and graphical UI, respectively. +``` +$ cmake .. -DOPTION_NAME=option_value +``` - ``` - $ ccmake .. - $ cmake-gui .. - ``` +Or use either the `ccmake` or `cmake-gui` front-ends, which display all options and their cached +values on a console and graphical UI, respectively. +``` +$ ccmake .. + $ cmake-gui .. +``` ## CMake Build for MSYS2 (MinGW) - **NOTE**: For development purposes it is preferred to use `MinGW Win64 Shell` or `MinGW Win32 Shell` instead of `MSYS2 Shell`. In other case, you will need to set `PATH` variable manually. - - For Mingw,MSYS,MSYS2 you should set [Makefiles generator](https://cmake.org/cmake/help/v3.0/manual/cmake-generators.7.html) to "MSYS Makefiles". - Setting it to "MinGW Makefiles" might work as well, but might also require additional hackery. - - Example: - - ``` - $ cd - $ mkdir build - $ cd build - $ cmake .. -G "MSYS Makefiles" - $ make # or $ cmake --build . - ``` - - The resulting binary will be placed inside the source code directory. - - Shared libraries: - - If you got `libgcc_s_dw2-1.dll not found` error you need to copy shared libraries - to directory with CataclysmBN executables. - - **NOTE**: For `-DRELEASE=OFF` development builds, You can automate copy process with: - - ``` - $ make install - ``` - - However, it likely will fail b/c you have different build environment setup :) - - Currently known depends (Maybe outdated use ldd.exe to correct it for Your system) - - * MINGW deps: - * `libwinpthread-1.dll` - * `libgcc_s_dw2-1.dll` - * `libstdc++-6.dll` - - * TILES deps: - * `SDL2.dll` - * `SDL2_ttf.dll` - * `libfreetype-6.dll` - * `libbz2-1.dll` - * `libharfbuzz-0.dll` - * `SDL2_image.dll` - * `libpng16-16.dll` - * `libjpeg-8.dll` - * `libtiff-5.dll` - * `libjbig-0.dll` - * `liblzma-5.dll` - * `libwebp-5.dll` - * `zlib1.dll` - * `libglib-2.0-0.dll` - - * SOUND deps: - * `SDL2_mixer.dll` - * `libFLAC-8.dll` - * `libogg-0.dll` - * `libfluidsynth-1.dll` - * `libportaudio-2.dll` - * `libsndfile-1.dll` - * `libvorbis-0.dll` - * `libvorbisenc-2.dll` - * `libmodplug-1.dll` - * `smpeg2.dll` - * `libvorbisfile-3.dll` +**NOTE**: For development purposes it is preferred to use `MinGW Win64 Shell` or `MinGW Win32 Shell` +instead of `MSYS2 Shell`. In other case, you will need to set `PATH` variable manually. + +For Mingw,MSYS,MSYS2 you should set +[Makefiles generator](https://cmake.org/cmake/help/v3.0/manual/cmake-generators.7.html) to "MSYS +Makefiles". Setting it to "MinGW Makefiles" might work as well, but might also require additional +hackery. + +Example: + +``` +$ cd + $ mkdir build + $ cd build + $ cmake .. -G "MSYS Makefiles" + $ make # or $ cmake --build . +``` + +The resulting binary will be placed inside the source code directory. + +Shared libraries: + +If you got `libgcc_s_dw2-1.dll not found` error you need to copy shared libraries to directory with +CataclysmBN executables. +**NOTE**: For `-DRELEASE=OFF` development builds, You can automate copy process with: + +``` +$ make install +``` + +However, it likely will fail b/c you have different build environment setup :) + +Currently known depends (Maybe outdated use ldd.exe to correct it for Your system) + +- MINGW deps: + - `libwinpthread-1.dll` + - `libgcc_s_dw2-1.dll` + - `libstdc++-6.dll` + +- TILES deps: + - `SDL2.dll` + - `SDL2_ttf.dll` + - `libfreetype-6.dll` + - `libbz2-1.dll` + - `libharfbuzz-0.dll` + - `SDL2_image.dll` + - `libpng16-16.dll` + - `libjpeg-8.dll` + - `libtiff-5.dll` + - `libjbig-0.dll` + - `liblzma-5.dll` + - `libwebp-5.dll` + - `zlib1.dll` + - `libglib-2.0-0.dll` + +- SOUND deps: + - `SDL2_mixer.dll` + - `libFLAC-8.dll` + - `libogg-0.dll` + - `libfluidsynth-1.dll` + - `libportaudio-2.dll` + - `libsndfile-1.dll` + - `libvorbis-0.dll` + - `libvorbisenc-2.dll` + - `libmodplug-1.dll` + - `smpeg2.dll` + - `libvorbisfile-3.dll` ## CMake Build for Visual Studio / MSBuild -CMake can generate `.sln` and `.vcxproj` files used either by Visual Studio itself or by MSBuild command line compiler (if you don't want -a full fledged IDE) and have more "native" binaries than what MSYS/Cygwin can provide. +CMake can generate `.sln` and `.vcxproj` files used either by Visual Studio itself or by MSBuild +command line compiler (if you don't want a full fledged IDE) and have more "native" binaries than +what MSYS/Cygwin can provide. -At the moment only a limited combination of options is supported (tiles only, no localizations, no backtrace). +At the moment only a limited combination of options is supported (tiles only, no localizations, no +backtrace). Get the tools: - * CMake from the official site - https://cmake.org/download/. - * Microsoft compiler - https://visualstudio.microsoft.com/downloads/?q=build+tools , choose "Build Tools for Visual Studio 2017". When installing chose "Visual C++ Build Tools" options. - * alternatively, you can get download and install the complete Visual Studio, but that's not required. + +- CMake from the official site - https://cmake.org/download/. +- Microsoft compiler - https://visualstudio.microsoft.com/downloads/?q=build+tools , choose "Build + Tools for Visual Studio 2017". When installing chose "Visual C++ Build Tools" options. + - alternatively, you can get download and install the complete Visual Studio, but that's not + required. Get the required libraries: - * `SDL2` - https://www.libsdl.org/download-2.0.php (you need the "(Visual C++ 32/64-bit)" version. Same below) - * `SDL2_ttf` - https://www.libsdl.org/projects/SDL_ttf/ - * `SDL2_image` - https://www.libsdl.org/projects/SDL_image/ - * `SDL2_mixer` (optional, for sound support) - https://www.libsdl.org/projects/SDL_mixer/ - * Unsupported (and unused in the following instructions) optional libs: - * `ncurses` - ??? + +- `SDL2` - https://www.libsdl.org/download-2.0.php (you need the "(Visual C++ 32/64-bit)" version. + Same below) +- `SDL2_ttf` - https://www.libsdl.org/projects/SDL_ttf/ +- `SDL2_image` - https://www.libsdl.org/projects/SDL_image/ +- `SDL2_mixer` (optional, for sound support) - https://www.libsdl.org/projects/SDL_mixer/ +- Unsupported (and unused in the following instructions) optional libs: + - `ncurses` - ??? Unpack the archives with the libraries. -Open windows command line (or powershell), set the environment variables to point to the libs above as follows (adjusting the paths as appropriate): +Open windows command line (or powershell), set the environment variables to point to the libs above +as follows (adjusting the paths as appropriate): + ``` - > set SDL2DIR=C:\path\to\SDL2-devel-2.0.9-VC - > set SDL2TTFDIR=C:\path\to\SDL2_ttf-devel-2.0.15-VC - > set SDL2IMAGEDIR=C:\path\to\SDL2_image-devel-2.0.4-VC - > set SDL2MIXERDIR=C:\path\to\SDL2_mixer-devel-2.0.4-VC +> set SDL2DIR=C:\path\to\SDL2-devel-2.0.9-VC +> set SDL2TTFDIR=C:\path\to\SDL2_ttf-devel-2.0.15-VC +> set SDL2IMAGEDIR=C:\path\to\SDL2_image-devel-2.0.4-VC +> set SDL2MIXERDIR=C:\path\to\SDL2_mixer-devel-2.0.4-VC ``` + (for powershell the syntax is `$env:SDL2DIR="C:\path\to\SDL2-devel-2.0.9-VC"`). Make a build directory and run cmake configuration step + ``` - > cd - > mkdir build - > cd build - > cmake .. -DTILES=ON -DLANGUAGES=none -DBACKTRACE=OFF -DSOUND=ON +> cd +> mkdir build +> cd build +> cmake .. -DTILES=ON -DLANGUAGES=none -DBACKTRACE=OFF -DSOUND=ON ``` - Build! + ``` - > cmake --build . -j 2 -- /p:Configuration=Release +> cmake --build . -j 2 -- /p:Configuration=Release ``` - The `-j 2` flag controls build parallelism - you can omit it if you wish. The `/p:Configuration=Release` flag is passed directly to MSBuild and - controls optimizations. If you omit it, the `Debug` configuration would be built instead. For powershell you'll need to have an extra ` -- ` after the first one. -The resulting files will be put into a `Release` directory inside your source Cataclysm-BN folder. To make them run you'd need to first move them to the -source Cataclysm-BN directory itself (so that the binary has access to the game data), and second put the required `.dll`s into the same folder - -you can find those inside the directories for dev libraries under `lib/x86/` or `lib/x64/` (you likely need the `x86` ones even if you're on 64-bit machine). +The `-j 2` flag controls build parallelism - you can omit it if you wish. The +`/p:Configuration=Release` flag is passed directly to MSBuild and controls optimizations. If you +omit it, the `Debug` configuration would be built instead. For powershell you'll need to have an +extra `--` after the first one. -The copying of dlls is a one-time task, but you'd need to move the binary out of `Release/` each time it's built. To automate it a bit, you can configure cmake and set the desired binaries destination directory with `-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=` option (and similar for `CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG`). +The resulting files will be put into a `Release` directory inside your source Cataclysm-BN folder. +To make them run you'd need to first move them to the source Cataclysm-BN directory itself (so that +the binary has access to the game data), and second put the required `.dll`s into the same folder - +you can find those inside the directories for dev libraries under `lib/x86/` or `lib/x64/` (you +likely need the `x86` ones even if you're on 64-bit machine). -Run the game. Should work. +The copying of dlls is a one-time task, but you'd need to move the binary out of `Release/` each +time it's built. To automate it a bit, you can configure cmake and set the desired binaries +destination directory with `-DCMAKE_RUNTIME_OUTPUT_DIRECTORY_RELEASE=` option (and similar for +`CMAKE_RUNTIME_OUTPUT_DIRECTORY_DEBUG`). +Run the game. Should work. # Build Options - A full list of options supported by CMake, you may either run the `ccmake` - or `cmake-gui` front-ends, or run `cmake` and open the generated CMakeCache.txt - from the build directory in a text editor. - - ``` - $ cmake -DOPTION_NAME1=option_value1 [-DOPTION_NAME2=option_value2 [...]] - ``` +A full list of options supported by CMake, you may either run the `ccmake` or `cmake-gui` +front-ends, or run `cmake` and open the generated CMakeCache.txt from the build directory in a text +editor. +``` +$ cmake -DOPTION_NAME1=option_value1 [-DOPTION_NAME2=option_value2 [...]] +``` ## CMake specific options - * CMAKE_BUILD_TYPE=`` +- CMAKE_BUILD_TYPE=`` - Selects a specific build configuration when compiling. `release` produces - the default, optimized (-Os) build for regular use. `debug` produces a - slower and larger unoptimized (-O0) build with full debug symbols, which is - often needed for obtaining detailed backtraces when reporting bugs. +Selects a specific build configuration when compiling. `release` produces the default, optimized +(-Os) build for regular use. `debug` produces a slower and larger unoptimized (-O0) build with full +debug symbols, which is often needed for obtaining detailed backtraces when reporting bugs. - **NOTE**: By default, CMake will produce `debug` builds unless a different - configuration option is passed in the command line. +**NOTE**: By default, CMake will produce `debug` builds unless a different configuration option is +passed in the command line. +- CMAKE_INSTALL_PREFIX=`` - * CMAKE_INSTALL_PREFIX=`` +Installation prefix for binaries, resources, and documentation files. - Installation prefix for binaries, resources, and documentation files. +## CataclysmBN specific options +- CURSES=`` -## CataclysmBN specific options +Build curses version. + +- TILES=`` - * CURSES=`` +Build graphical tileset version. - Build curses version. +- SOUND=`` +Support for in-game sounds & music. - * TILES=`` +- USE_HOME_DIR=`` - Build graphical tileset version. +Use user's home directory for save files. +- LANGUAGES=`` - * SOUND=`` +Compile localization files for specified languages. Example: - Support for in-game sounds & music. +``` +-DLANGUAGES="cs;de;el;es_AR;es_ES" +``` +Note that language files are only compiled automatically when building the `RELEASE` build type. For +other build types, you need to add the `translations_compile` target to the `make` command, for +example `make all translations_compile`. - * USE_HOME_DIR=`` +- DYNAMIC_LINKING=`` - Use user's home directory for save files. +Use dynamic linking. Or use static to remove MinGW dependency instead. +- CUSTOM LINKER=`` - * LANGUAGES=`` +Choose custom linkers such as [gold], [lld] or [mold]. - Compile localization files for specified languages. Example: - ``` - -DLANGUAGES="cs;de;el;es_AR;es_ES" - ``` +- Choose ld if you don't use libbacktrace. +- Choose mold if use libbacktrace. It's the fastest linker, outperforming gold by 24x. - Note that language files are only compiled automatically when building the - `RELEASE` build type. For other build types, you need to add the `translations_compile` - target to the `make` command, for example `make all translations_compile`. +[gold]: https://en.wikipedia.org/wiki/Gold_(linker) +[lld]: https://lld.llvm.org +[mold]: https://github.com/rui314/mold +- BACKTRACE=`` - * DYNAMIC_LINKING=`` +On crash, print a backtrace to the console. Defaults to `ON` for debug builds. - Use dynamic linking. Or use static to remove MinGW dependency instead. +- LIBBACKTRACE=`` +Print backtrace with [libbacktrace]. This allows lld and mold to print backtrace, and is generally +much faster. - * GIT_BINARY=`` +[libbacktrace]: https://github.com/ianlancetaylor/libbacktrace - Override default Git binary name or path. +- GIT_BINARY=`` - So a CMake command for building Cataclysm-BN in release mode with tiles and sound support will look as follows, provided it is run in build directory located in the project. -``` +Override default Git binary name or path. + +So a CMake command for building Cataclysm-BN in release mode with tiles and sound support will look +as follows, provided it is run in build directory located in the project. + +```sh cmake ../ -DCMAKE_BUILD_TYPE=Release -DTILES=ON -DSOUND=ON ``` - diff --git a/doc/COMPILING/COMPILING-CYGWIN.md b/doc/COMPILING/COMPILING-CYGWIN.md index 9ccf4c6bb47d..c2540409c77f 100644 --- a/doc/COMPILING/COMPILING-CYGWIN.md +++ b/doc/COMPILING/COMPILING-CYGWIN.md @@ -1,22 +1,32 @@ # Compilation guide for 64 bit Windows (using Cygwin) -This guide contains instructions for compiling Cataclysm-BN on Windows under Cygwin. **PLEASE NOTE:** These instructions *are not intended* to produce a redistributable copy of CBN. Please download the official builds from the website or [cross-compile from Linux](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/master/doc/COMPILING/COMPILING.md#cross-compile-to-windows-from-linux) if that is your intention. +This guide contains instructions for compiling Cataclysm-BN on Windows under Cygwin. **PLEASE +NOTE:** These instructions _are not intended_ to produce a redistributable copy of CBN. Please +download the official builds from the website or +[cross-compile from Linux](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/master/doc/COMPILING/COMPILING.md#cross-compile-to-windows-from-linux) +if that is your intention. -These instructions were written using 64-bit Windows 7 and the 64-bit version of Cygwin; the steps should be the same for other versions of Windows. +These instructions were written using 64-bit Windows 7 and the 64-bit version of Cygwin; the steps +should be the same for other versions of Windows. -Due to slow environment setup and execution of the resulting binary, compilation using MSYS2 is preferred. +Due to slow environment setup and execution of the resulting binary, compilation using MSYS2 is +preferred. ## Prerequisites: -* 64-bit version of Windows 7, 8, 8.1, or 10 -* NTFS partition with ~10 Gb free space (~2 Gb for Cygwin installation, ~3 Gb for repository and ~5 Gb for ccache) -* 64-bit version of Cygwin +- 64-bit version of Windows 7, 8, 8.1, or 10 +- NTFS partition with ~10 Gb free space (~2 Gb for Cygwin installation, ~3 Gb for repository and ~5 + Gb for ccache) +- 64-bit version of Cygwin ## Installation: -1. Go to the [Cygwin homepage](https://cygwin.com/) and download the 64-bit installer (e.g. [setup-x86_64.exe](https://cygwin.com/setup-x86_64.exe)). +1. Go to the [Cygwin homepage](https://cygwin.com/) and download the 64-bit installer (e.g. + [setup-x86_64.exe](https://cygwin.com/setup-x86_64.exe)). -2. Run downloaded file and install Cygwin. Select `Install from Internet` and select the desired installation directory. It is suggested that you install into a dev-specific directory (e.g. `C:\dev\cygwin64`), but it's not strictly necessary. Install for all users. +2. Run downloaded file and install Cygwin. Select `Install from Internet` and select the desired + installation directory. It is suggested that you install into a dev-specific directory (e.g. + `C:\dev\cygwin64`), but it's not strictly necessary. Install for all users. 3. Give the `\downloads\` folder as the local package directory (e.g. `C:\dev\cygwin64\downloads`). @@ -24,9 +34,11 @@ Due to slow environment setup and execution of the resulting binary, compilation 5. On the next screen, select any mirror you like. -6. Enter `wget` into the search box, expand the "Web" category and select the latest version in the drop-down (1.21.1-1 as of the time this guide was written). +6. Enter `wget` into the search box, expand the "Web" category and select the latest version in the + drop-down (1.21.1-1 as of the time this guide was written). -7. Confirm that wget is shown in the following screen by scrolling to the bottom. This is the full list of packages that Cygwin will download and install. +7. Confirm that wget is shown in the following screen by scrolling to the bottom. This is the full + list of packages that Cygwin will download and install. 8. Retry any packages that throw errors. @@ -49,13 +61,16 @@ chmod 755 /bin/apt-cyg apt-cyg install astyle ccache gcc-g++ intltool git libSDL2_image-devel libSDL2_mixer-devel libSDL2_ttf-devel make xinit ``` -You will see messages saying packages are already installed, as well as Cygwin installing packages you didn't ask for; this is the result of Cygwin's package manager automatically resolving dependencies. +You will see messages saying packages are already installed, as well as Cygwin installing packages +you didn't ask for; this is the result of Cygwin's package manager automatically resolving +dependencies. ## Cloning and compilation: 1. Clone the Cataclysm-BN repository with following command: -**Note:** This will download the entire CBN repository and all of its history (3GB). If you're just testing, you should probably add `--depth=1` (~350MB). +**Note:** This will download the entire CBN repository and all of its history (3GB). If you're just +testing, you should probably add `--depth=1` (~350MB). ```bash cd /cygdrive/c/dev @@ -69,15 +84,19 @@ cd Cataclysm-BN make -j$((`nproc`+0)) CCACHE=1 RELEASE=1 CYGWIN=1 DYNAMIC_LINKING=1 SDL=1 TILES=1 SOUND=1 LANGUAGES=all LINTJSON=0 ASTYLE=0 BACKTRACE=0 RUNTESTS=0 ``` -You will receive warnings about unterminated character constants; they do not impact the compilation as far as this writer is aware. +You will receive warnings about unterminated character constants; they do not impact the compilation +as far as this writer is aware. -**Note**: This will compile release version with Sound and Tiles support and all localization languages, skipping checks and tests and using ccache for faster build. You can use other switches, but `CYGWIN=1`, `DYNAMIC_LINKING=1` and `BACKTRACE=0` are required to compile without issues. +**Note**: This will compile release version with Sound and Tiles support and all localization +languages, skipping checks and tests and using ccache for faster build. You can use other switches, +but `CYGWIN=1`, `DYNAMIC_LINKING=1` and `BACKTRACE=0` are required to compile without issues. ## Running: 1. Execute the XWin Server from the Start menu. -2. When the icons appear in the system tray, right-click the one that looks like a black C (X Applications Menu.) +2. When the icons appear in the system tray, right-click the one that looks like a black C (X + Applications Menu.) 3. Point to System Tools, then click UXTerm. diff --git a/doc/COMPILING/COMPILING-MSYS.md b/doc/COMPILING/COMPILING-MSYS.md index 9a12ae803d41..d40984040c13 100644 --- a/doc/COMPILING/COMPILING-MSYS.md +++ b/doc/COMPILING/COMPILING-MSYS.md @@ -1,14 +1,20 @@ # Compilation guide for 64-bit Windows (using MSYS2) -This guide contains instructions for compiling Cataclysm-BN on Windows under MSYS2. **PLEASE NOTE:** These instructions *are not intended* to produce a redistributable copy of CBN. Please download the official builds from the website or [cross-compile from Linux](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/master/doc/COMPILING/COMPILING.md#cross-compile-to-windows-from-linux) if that is your intention. +This guide contains instructions for compiling Cataclysm-BN on Windows under MSYS2. **PLEASE NOTE:** +These instructions _are not intended_ to produce a redistributable copy of CBN. Please download the +official builds from the website or +[cross-compile from Linux](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/master/doc/COMPILING/COMPILING.md#cross-compile-to-windows-from-linux) +if that is your intention. -These instructions were written using 64-bit Windows 7 and the 64-bit version of MSYS2; the steps should be the same for other versions of Windows. +These instructions were written using 64-bit Windows 7 and the 64-bit version of MSYS2; the steps +should be the same for other versions of Windows. ## Prerequisites: -* Windows 7, 8, 8.1, or 10 -* NTFS partition with ~10 Gb free space (~2 Gb for MSYS2 installation, ~3 Gb for repository and ~5 Gb for ccache) -* 64-bit version of MSYS2 +- Windows 7, 8, 8.1, or 10 +- NTFS partition with ~10 Gb free space (~2 Gb for MSYS2 installation, ~3 Gb for repository and ~5 + Gb for ccache) +- 64-bit version of MSYS2 **Note:** Windows XP is unsupported! @@ -16,7 +22,8 @@ These instructions were written using 64-bit Windows 7 and the 64-bit version of 1. Go to the [MSYS2 homepage](http://www.msys2.org/) and download the installer. -2. Run the installer. It is suggested that you install to a dev-specific folder (C:\dev\msys64\ or similar), but it's not strictly necessary. +2. Run the installer. It is suggested that you install to a dev-specific folder (C:\dev\msys64\ or + similar), but it's not strictly necessary. 3. After installation, run MSYS2 64bit now. @@ -28,7 +35,10 @@ These instructions were written using 64-bit Windows 7 and the 64-bit version of pacman -Syyu ``` -2. MSYS may inform you of a cygheap base mismatch and inform you a forked process died unexpectedly; these errors appear to be due to the nature of `pacman`'s upgrades and *may be safely ignored.* You will be prompted to close the terminal window; do so, then re-start using the MSYS2 MinGW 64-bit menu item. +2. MSYS may inform you of a cygheap base mismatch and inform you a forked process died unexpectedly; + these errors appear to be due to the nature of `pacman`'s upgrades and _may be safely ignored._ + You will be prompted to close the terminal window; do so, then re-start using the MSYS2 MinGW + 64-bit menu item. 3. Update remaining packages: @@ -44,34 +54,35 @@ pacman -S git make mingw-w64-x86_64-{astyle,ccache,gcc,libmad,libwebp,pkg-config 5. Close MSYS2. -6. Update path variables in the system-wide profile file (e.g. `C:\dev\msys64\etc\profile`) as following: +6. Update path variables in the system-wide profile file (e.g. `C:\dev\msys64\etc\profile`) as + following: - find lines: ``` - MSYS2_PATH="/usr/local/bin:/usr/bin:/bin" - MANPATH='/usr/local/man:/usr/share/man:/usr/man:/share/man' - INFOPATH='/usr/local/info:/usr/share/info:/usr/info:/share/info' +MSYS2_PATH="/usr/local/bin:/usr/bin:/bin" +MANPATH='/usr/local/man:/usr/share/man:/usr/man:/share/man' +INFOPATH='/usr/local/info:/usr/share/info:/usr/info:/share/info' ``` and ``` - PKG_CONFIG_PATH="/usr/lib/pkgconfig:/usr/share/pkgconfig:/lib/pkgconfig" +PKG_CONFIG_PATH="/usr/lib/pkgconfig:/usr/share/pkgconfig:/lib/pkgconfig" ``` - and replace them with: ``` - MSYS2_PATH="/usr/local/bin:/usr/bin:/bin:/mingw64/bin" - MANPATH='/usr/local/man:/usr/share/man:/usr/man:/share/man:/mingw64/share/man' - INFOPATH='/usr/local/info:/usr/share/info:/usr/info:/share/info:/mingw64/share/man' +MSYS2_PATH="/usr/local/bin:/usr/bin:/bin:/mingw64/bin" +MANPATH='/usr/local/man:/usr/share/man:/usr/man:/share/man:/mingw64/share/man' +INFOPATH='/usr/local/info:/usr/share/info:/usr/info:/share/info:/mingw64/share/man' ``` and ``` - PKG_CONFIG_PATH="/usr/lib/pkgconfig:/usr/share/pkgconfig:/lib/pkgconfig:/mingw64/lib/pkgconfig:/mingw64/share/pkgconfig" +PKG_CONFIG_PATH="/usr/lib/pkgconfig:/usr/share/pkgconfig:/lib/pkgconfig:/mingw64/lib/pkgconfig:/mingw64/share/pkgconfig" ``` ## Cloning and compilation: @@ -84,7 +95,8 @@ git clone https://github.com/cataclysmbnteam/Cataclysm-BN.git cd Cataclysm-BN ``` -**Note:** This will download the entire CBN repository and all of its history (3GB). If you're just testing, you should probably add `--depth=1` (~350MB). +**Note:** This will download the entire CBN repository and all of its history (3GB). If you're just +testing, you should probably add `--depth=1` (~350MB). 2. Compile with following command line: @@ -92,9 +104,12 @@ cd Cataclysm-BN make -j$((`nproc`+0)) CCACHE=1 RELEASE=1 MSYS2=1 DYNAMIC_LINKING=1 SDL=1 TILES=1 SOUND=1 LANGUAGES=all LINTJSON=0 ASTYLE=0 RUNTESTS=0 ``` -You will receive warnings about unterminated character constants; they do not impact the compilation as far as this writer is aware. +You will receive warnings about unterminated character constants; they do not impact the compilation +as far as this writer is aware. -**Note**: This will compile a release version with Sound and Tiles support and all localization languages, skipping checks and tests, and using ccache for build acceleration. You can use other switches, but `MSYS2=1` and `DYNAMIC_LINKING=1` are required to compile without issues. +**Note**: This will compile a release version with Sound and Tiles support and all localization +languages, skipping checks and tests, and using ccache for build acceleration. You can use other +switches, but `MSYS2=1` and `DYNAMIC_LINKING=1` are required to compile without issues. ## Running: @@ -104,4 +119,6 @@ You will receive warnings about unterminated character constants; they do not im ./cataclysm-tiles ``` -**Note:** If you want to run the compiled executable outside of MSYS2, you will also need to update your user or system `PATH` variable with the path to MSYS2's runtime binaries (e.g. `C:\dev\msys64\mingw64\bin`). +**Note:** If you want to run the compiled executable outside of MSYS2, you will also need to update +your user or system `PATH` variable with the path to MSYS2's runtime binaries (e.g. +`C:\dev\msys64\mingw64\bin`). diff --git a/doc/COMPILING/COMPILING-VS-VCPKG.md b/doc/COMPILING/COMPILING-VS-VCPKG.md index d15b766f1e28..2b02b8fcd8ba 100644 --- a/doc/COMPILING/COMPILING-VS-VCPKG.md +++ b/doc/COMPILING/COMPILING-VS-VCPKG.md @@ -1,32 +1,45 @@ # Compilation guide for Windows (using Visual Studio and vcpkg) -This guide contains steps required to allow compilation of Cataclysm-BN on Windows using Visual Studio and vcpkg. +This guide contains steps required to allow compilation of Cataclysm-BN on Windows using Visual +Studio and vcpkg. -Steps from current guide were tested on Windows 10 and 11 (64 bit), Visual Studio 2019 and 2022 (64 bit), but should as well work with slight modifications for other versions of Windows and Visual Studio. +Steps from current guide were tested on Windows 10 and 11 (64 bit), Visual Studio 2019 and 2022 (64 +bit), but should as well work with slight modifications for other versions of Windows and Visual +Studio. ## Prerequisites: -* Computer with modern Windows operating system installed (Windows 10 or 11), Windows 7 and 8.1 are not guaranteed to work; -* NTFS partition with ~15 Gb free space (~10 Gb for Visual Studio, ~1 Gb for vcpkg installation, ~3 Gb for repository and ~1 Gb for build cache); -* Git for Windows (installer can be downloaded from [Git homepage](https://git-scm.com/)); -* Visual Studio 2019 or 2022 - * **Note**: If you are using Visual Studio 2022, you must install the Visual Studio 2019 compilers to work around a vcpkg bug. In the Visual Studio Installer, select the 'Individual components' tab and search for / select the component that looks like 'MSVC v142 - VS 2019 C++ x64/x86 Build Tools'. See https://github.com/microsoft/vcpkg/issues/22287. -* Latest version of vcpkg (see instructions on [vcpkg homepage](https://github.com/Microsoft/vcpkg)). -* If you plan on contributing your changes to Bright Nights, you'll also have to install a code formatter, see [Code style](#code-style) section for more info. +- Computer with modern Windows operating system installed (Windows 10 or 11), Windows 7 and 8.1 are + not guaranteed to work; +- NTFS partition with ~15 Gb free space (~10 Gb for Visual Studio, ~1 Gb for vcpkg installation, ~3 + Gb for repository and ~1 Gb for build cache); +- Git for Windows (installer can be downloaded from [Git homepage](https://git-scm.com/)); +- Visual Studio 2019 or 2022 + - **Note**: If you are using Visual Studio 2022, you must install the Visual Studio 2019 compilers + to work around a vcpkg bug. In the Visual Studio Installer, select the 'Individual components' + tab and search for / select the component that looks like 'MSVC v142 - VS 2019 C++ x64/x86 Build + Tools'. See https://github.com/microsoft/vcpkg/issues/22287. +- Latest version of vcpkg (see instructions on + [vcpkg homepage](https://github.com/Microsoft/vcpkg)). +- If you plan on contributing your changes to Bright Nights, you'll also have to install a code + formatter, see [Code style](#code-style) section for more info. **Note:** Windows XP is unsupported! ## Installation and configuration: -1. Install `Visual Studio` (installer can be downloaded from [Visual Studio homepage](https://visualstudio.microsoft.com/)). +1. Install `Visual Studio` (installer can be downloaded from + [Visual Studio homepage](https://visualstudio.microsoft.com/)). - Select the "Desktop development with C++" and "Game development with C++" workloads. -2. Install `Git for Windows` (installer can be downloaded from [Git homepage](https://git-scm.com/)). +2. Install `Git for Windows` (installer can be downloaded from + [Git homepage](https://git-scm.com/)). 3. Install and configure latest `vcpkg`: -***WARNING: It is important that, wherever you decide to clone this repo, the path does not include whitespace. That is, `C:/dev/vcpkg` is acceptable, but `C:/dev test/vcpkg` is not.*** +_**WARNING: It is important that, wherever you decide to clone this repo, the path does not include +whitespace. That is, `C:/dev/vcpkg` is acceptable, but `C:/dev test/vcpkg` is not.**_ ```cmd git clone https://github.com/Microsoft/vcpkg.git @@ -39,36 +52,57 @@ vcpkg integrate install 1. Clone Cataclysm-BN repository with following command line: -**Note:** This will download the entire CBN repository; 3+ GB of data. If you're just testing you should probably add `--depth=1`. +**Note:** This will download the entire CBN repository; 3+ GB of data. If you're just testing you +should probably add `--depth=1`. ```cmd git clone https://github.com/cataclysmbnteam/Cataclysm-BN.git cd Cataclysm-BN ``` -2. Open the provided solution (`msvc-full-features\Cataclysm-vcpkg-static.sln`) in `Visual Studio`, select configuration (`Release` is advised if you just want to compile, `Debug` is if you're planning on editing code) and platform (`x64` or `x86`) and build it. All necessary dependencies will be built and cached for future use by vcpkg automatically. +2. Open the provided solution (`msvc-full-features\Cataclysm-vcpkg-static.sln`) in `Visual Studio`, + select configuration (`Release` is advised if you just want to compile, `Debug` is if you're + planning on editing code) and platform (`x64` or `x86`) and build it. All necessary dependencies + will be built and cached for future use by vcpkg automatically. -3. Open the `Build > Configuration Manager` menu and adjust `Active solution configuration` and `Active solution platform` to match your intended target. +3. Open the `Build > Configuration Manager` menu and adjust `Active solution configuration` and + `Active solution platform` to match your intended target. -This will configure Visual Studio to compile the release version, with support for Sound, Tiles, and Localization (note, however, that language files themselves are not automatically compiled; this will be done later). +This will configure Visual Studio to compile the release version, with support for Sound, Tiles, and +Localization (note, however, that language files themselves are not automatically compiled; this +will be done later). -4. Start the build process by selecting either `Build > Build Solution` or `Build > Build > Cataclysm-vcpkg-static`. The process may take a long period of time, so you'd better prepare a cup of coffee and some books in front of your computer :) The first build of each architecture will also download and install dependencies through vcpkg, which can take an especially long time. +4. Start the build process by selecting either `Build > Build Solution` or + `Build > Build > Cataclysm-vcpkg-static`. The process may take a long period of time, so you'd + better prepare a cup of coffee and some books in front of your computer :) The first build of + each architecture will also download and install dependencies through vcpkg, which can take an + especially long time. -5. If you want to launch the game directly from Visual Studio, make sure you have specified correct working directory as explained below. Otherwise, you'll only be able to launch the game from the file explorer. +5. If you want to launch the game directly from Visual Studio, make sure you have specified correct + working directory as explained below. Otherwise, you'll only be able to launch the game from the + file explorer. -6. If you need localization support, execute the bash script `lang/compile_mo.sh` inside Git Bash GUI just like on a UNIX-like system. This will compile the language files that were not automatically compiled in step 2 above. +6. If you need localization support, execute the bash script `lang/compile_mo.sh` inside Git Bash + GUI just like on a UNIX-like system. This will compile the language files that were not + automatically compiled in step 2 above. ### Running from Visual Studio and debugging -1. Ensure that the Cataclysm game binary project (`Cataclysm-vcpkg-static`) is the selected startup project (right click on it in Solution Explorer -> `Set as Startup Project`) +1. Ensure that the Cataclysm game binary project (`Cataclysm-vcpkg-static`) is the selected startup + project (right click on it in Solution Explorer -> `Set as Startup Project`) -2. Configure the working directory in the project properties to `$(ProjectDir)..` (right click on it in Solution Explorer -> `Properties` -> select `All Configurations` and `All Platforms` at the top -> `Debugging` -> `Working Directory`) +2. Configure the working directory in the project properties to `$(ProjectDir)..` (right click on it + in Solution Explorer -> `Properties` -> select `All Configurations` and `All Platforms` at the + top -> `Debugging` -> `Working Directory`) -3. Press the debug button (green right-facing triangle near the top, or use the appropriate shortcut, e.g. F5) +3. Press the debug button (green right-facing triangle near the top, or use the appropriate + shortcut, e.g. F5) -If you discover that after pressing the debug button in Visual Studio, Cataclysm just exits after launch with return code 1, that is because of the wrong working directory. +If you discover that after pressing the debug button in Visual Studio, Cataclysm just exits after +launch with return code 1, that is because of the wrong working directory. ### Debug vs Release builds + `Debug` builds run significantly slower than `Release` builds, but provide additional safety checks. If you just want to build the executable and play the game, `Release` is advised. @@ -76,26 +110,43 @@ If you just want to build the executable and play the game, `Release` is advised If you plan on editing the code, `Debug` is advised. If you have enough experience with C++ to know: + - under-the-hood differences between `Debug` and `Release` - how `Release` optimizations may affect the debugger - how to avoid undefined behavior in code -Then you might want to use `Release` build all the time to speed up dev process, and disable optimizations on a file-by-file basis by adding +Then you might want to use `Release` build all the time to speed up dev process, and disable +optimizations on a file-by-file basis by adding + ```c++ #pragma optimize("", off) ``` + line at the top of the file. ### Running unit tests -Ensure that the Cataclysm test binary project (`Cataclysm-test-vcpkg-static`) is the selected startup project, configure the working directory in the project properties to `$(ProjectDir)..`, and then press the debug button (or use the appropriate shortcut, e.g. F5). This will run all of the unit tests. Additional command line arguments may be configured in the project's command line arguments setting, or if you are using a compatible unit test runner (e.g. Resharper) you can run or debug individual tests from the unit test sessions. +Ensure that the Cataclysm test binary project (`Cataclysm-test-vcpkg-static`) is the selected +startup project, configure the working directory in the project properties to `$(ProjectDir)..`, and +then press the debug button (or use the appropriate shortcut, e.g. F5). This will run all of the +unit tests. Additional command line arguments may be configured in the project's command line +arguments setting, or if you are using a compatible unit test runner (e.g. Resharper) you can run or +debug individual tests from the unit test sessions. ### Code style -We use `Artistic Style` source code formatter to keep the style of our C++ code consistent. While it's available as pre-built Windows executables, which you could install and run or configure to automatically format the code before commit, a much more convenient option for Visual Studio users is to install a specific extension, see ["Astyle extensions for Visual Studio" in doc/DEVELOPER_TOOLING.md](../DEVELOPER_TOOLING.md#astyle-extensions-for-visual-studio) for more info. +We use `Artistic Style` source code formatter to keep the style of our C++ code consistent. While +it's available as pre-built Windows executables, which you could install and run or configure to +automatically format the code before commit, a much more convenient option for Visual Studio users +is to install a specific extension, see +["Astyle extensions for Visual Studio" in doc/DEVELOPER_TOOLING.md](../DEVELOPER_TOOLING.md#astyle-extensions-for-visual-studio) +for more info. -As of October 2022, the code style check is run automatically on each PR on GitHub, so if you forgot to style your changes you'll see the corresponsing check failing. +As of October 2022, the code style check is run automatically on each PR on GitHub, so if you forgot +to style your changes you'll see the corresponsing check failing. ### Make a distribution -There is a batch script in `msvc-full-features` folder `distribute.bat`. It will create a sub folder `distribution` and copy all required files(eg. `data/`, `Cataclysm.exe` and dlls) into that folder. Then you can zip it and share the archive on the Internet. +There is a batch script in `msvc-full-features` folder `distribute.bat`. It will create a sub folder +`distribution` and copy all required files(eg. `data/`, `Cataclysm.exe` and dlls) into that folder. +Then you can zip it and share the archive on the Internet. diff --git a/doc/COMPILING/COMPILING.md b/doc/COMPILING/COMPILING.md index 54596af3d589..9a73208bf9e3 100644 --- a/doc/COMPILING/COMPILING.md +++ b/doc/COMPILING/COMPILING.md @@ -46,26 +46,32 @@ - [Building with CYGWIN](#building-with-cygwin) - [Building with Clang and MinGW64](#building-with-clang-and-mingw64) - [BSDs](#bsds) - - [Building on FreeBSD/amd64 10.1 with the system compiler](#building-on-freebsdamd64-101-with-the-system-compiler) - - [Building ncurses version on FreeBSD/amd64 9.3 with GCC 4.8.4 from ports](#building-ncurses-version-on-freebsdamd64-93-with-gcc-484-from-ports) - - [Building on OpenBSD/amd64 5.8 with GCC 4.9.2 from ports/packages](#building-on-openbsdamd64-58-with-gcc-492-from-portspackages) - - [Building on NetBSD/amd64 7.0RC1 with the system compiler](#building-on-netbsdamd64-70rc1-with-the-system-compiler) + - [Building on FreeBSD/amd64 10.1 with the system compiler](#building-on-freebsdamd64-101-with-the-system-compiler) + - [Building ncurses version on FreeBSD/amd64 9.3 with GCC 4.8.4 from ports](#building-ncurses-version-on-freebsdamd64-93-with-gcc-484-from-ports) + - [Building on OpenBSD/amd64 5.8 with GCC 4.9.2 from ports/packages](#building-on-openbsdamd64-58-with-gcc-492-from-portspackages) + - [Building on NetBSD/amd64 7.0RC1 with the system compiler](#building-on-netbsdamd64-70rc1-with-the-system-compiler) # General Linux Guide -To build Cataclysm from source you will need at least a C++ compiler, some basic developer tools, and necessary build dependencies. The exact package names vary greatly from distro to distro, so this part of the guide is intended to give you higher-level understanding of the process. +To build Cataclysm from source you will need at least a C++ compiler, some basic developer tools, +and necessary build dependencies. The exact package names vary greatly from distro to distro, so +this part of the guide is intended to give you higher-level understanding of the process. ## Compiler You have three major choices here: GCC, Clang and MXE. - * GCC is almost always the default on Linux systems so it's likely you already have it - * Clang is usually faster than GCC, so it's worth installing if you plan to keep up with the latest experimentals - * MXE is a cross-compiler, so of any importance only if you plan to compile for Windows on your Linux machine +- GCC is almost always the default on Linux systems so it's likely you already have it +- Clang is usually faster than GCC, so it's worth installing if you plan to keep up with the latest + experimentals +- MXE is a cross-compiler, so of any importance only if you plan to compile for Windows on your + Linux machine -(Note that your distro may have separate packages e.g. `gcc` only includes the C compiler and for C++ you'll need to install `g++`.) +(Note that your distro may have separate packages e.g. `gcc` only includes the C compiler and for +C++ you'll need to install `g++`.) -Cataclysm is targeting C++14 standard and that means you'll need a compiler that supports it. You can easily check if your version of `g++` supports C++14 by running: +Cataclysm is targeting C++14 standard and that means you'll need a compiler that supports it. You +can easily check if your version of `g++` supports C++14 by running: $ g++ --std=c++14 g++: fatal error: no input files @@ -81,82 +87,97 @@ The general rule is the newer the compiler the better. ## Tools -Most distros seem to package essential build tools as either a single package (Debian and derivatives have `build-essential`) or a package group (Arch has `base-devel`). You should use the above if available. Otherwise you'll at least need `make` and figure out the missing dependencies as you go (if any). +Most distros seem to package essential build tools as either a single package (Debian and +derivatives have `build-essential`) or a package group (Arch has `base-devel`). You should use the +above if available. Otherwise you'll at least need `make` and figure out the missing dependencies as +you go (if any). Besides the essentials you will need `git`. -If you plan on keeping up with experimentals you should also install `ccache`, which will considerably speed-up partial builds. +If you plan on keeping up with experimentals you should also install `ccache`, which will +considerably speed-up partial builds. ## Dependencies -There are some general dependencies, optional dependencies and then specific dependencies for either curses or tiles builds. The exact package names again depend on the distro you're using, and whether your distro packages libraries and their development files separately (e.g. Debian and derivatives). +There are some general dependencies, optional dependencies and then specific dependencies for either +curses or tiles builds. The exact package names again depend on the distro you're using, and whether +your distro packages libraries and their development files separately (e.g. Debian and derivatives). Rough list based on building on Arch: - * General: `gcc-libs`, `glibc`, `zlib`, `bzip2` - * Optional: `intltool` - * Curses: `ncurses` - * Tiles: `sdl2`, `sdl2_image`, `sdl2_ttf`, `sdl2_mixer`, `freetype2` +- General: `gcc-libs`, `glibc`, `zlib`, `bzip2` +- Optional: `intltool` +- Curses: `ncurses` +- Tiles: `sdl2`, `sdl2_image`, `sdl2_ttf`, `sdl2_mixer`, `freetype2` -E.g. for curses build on Debian and derivatives you'll also need `libncurses5-dev` or `libncursesw5-dev`. +E.g. for curses build on Debian and derivatives you'll also need `libncurses5-dev` or +`libncursesw5-dev`. Note on optional dependencies: - * `intltool` - for building localization files; if you plan to only use English you can skip it +- `intltool` - for building localization files; if you plan to only use English you can skip it -You should be able to figure out what you are missing by reading the compilation errors and/or the output of `ldd` for compiled binaries. +You should be able to figure out what you are missing by reading the compilation errors and/or the +output of `ldd` for compiled binaries. ## Make flags Given you're building from source you have a number of choices to make: - * `NATIVE=` - you should only care about this if you're cross-compiling - * `RELEASE=1` - without this you'll get a debug build (see note below) - * `LTO=1` - enables link-time optimization with GCC/Clang - * `TILES=1` - with this you'll get the tiles version, without it the curses version - * `SOUND=1` - if you want sound; this requires `TILES=1` - * `LANGUAGES=` - specifies localizations. See details [here](#compiling-localization-files) - * `CLANG=1` - use Clang instead of GCC - * `CCACHE=1` - use ccache - * `USE_LIBCXX=1` - use libc++ instead of libstdc++ with Clang (default on OS X) +- `NATIVE=` - you should only care about this if you're cross-compiling +- `RELEASE=1` - without this you'll get a debug build (see note below) +- `LTO=1` - enables link-time optimization with GCC/Clang +- `TILES=1` - with this you'll get the tiles version, without it the curses version +- `SOUND=1` - if you want sound; this requires `TILES=1` +- `LANGUAGES=` - specifies localizations. See details [here](#compiling-localization-files) +- `CLANG=1` - use Clang instead of GCC +- `CCACHE=1` - use ccache +- `USE_LIBCXX=1` - use libc++ instead of libstdc++ with Clang (default on OS X) There is a couple of other possible options - feel free to read the `Makefile`. -If you have a multi-core computer you'd probably want to add `-jX` to the options, where `X` should roughly be twice the number of cores you have available. +If you have a multi-core computer you'd probably want to add `-jX` to the options, where `X` should +roughly be twice the number of cores you have available. Example: `make -j4 CLANG=1 CCACHE=1 NATIVE=linux64 RELEASE=1 TILES=1` -The above will build a tiles release explicitly for 64 bit Linux, using Clang and ccache and 4 parallel processes. +The above will build a tiles release explicitly for 64 bit Linux, using Clang and ccache and 4 +parallel processes. Example: `make -j2` -The above will build a debug-enabled curses version for the architecture you are using, using GCC and 2 parallel processes. +The above will build a debug-enabled curses version for the architecture you are using, using GCC +and 2 parallel processes. -**Note on debug**: -You should probably always build with `RELEASE=1` unless you experience segfaults and are willing to provide stack traces. +**Note on debug**: You should probably always build with `RELEASE=1` unless you experience segfaults +and are willing to provide stack traces. ## Compiling localization files By default, only English language is available, and it does not require localization file. -If you want to compile files for specific languages, you should add `LANGUAGES=" [lang_id_2] [...]"` option to make command: +If you want to compile files for specific languages, you should add +`LANGUAGES=" [lang_id_2] [...]"` option to make command: make LANGUAGES="zh_CN zh_TW" -You can get the language ID from the filenames of `*.po` in `lang/po` directory or use `LANGUAGES="all"` to compile all available localizations. +You can get the language ID from the filenames of `*.po` in `lang/po` directory or use +`LANGUAGES="all"` to compile all available localizations. # Debian -Instructions for compiling on a Debian-based system. The package names here are valid for Ubuntu 12.10 and may or may not work on your system. +Instructions for compiling on a Debian-based system. The package names here are valid for Ubuntu +12.10 and may or may not work on your system. -Building instructions, below, always assume you are running them from the Cataclysm:BN source directory. +Building instructions, below, always assume you are running them from the Cataclysm:BN source +directory. ## Linux (native) ncurses builds Dependencies: - * ncurses or ncursesw (for multi-byte locales) - * build essentials +- ncurses or ncursesw (for multi-byte locales) +- build essentials Install: @@ -172,22 +193,25 @@ Run: Dependencies: - * SDL - * SDL_ttf - * freetype - * build essentials - * libsdl2-mixer-dev - Used if compiling with sound support. +- SDL +- SDL_ttf +- freetype +- build essentials +- libsdl2-mixer-dev - Used if compiling with sound support. Install: sudo apt-get install libsdl2-dev libsdl2-ttf-dev libsdl2-image-dev libsdl2-mixer-dev libfreetype6-dev build-essential check correct version of SDL2 is installed by running: + ```sh > sdl2-config --version 2.0.22 ``` -using old version of SDL could result in [IME not working.](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/1497) + +using old version of SDL could result in +[IME not working.](https://github.com/cataclysmbnteam/Cataclysm-BN/issues/1497) ### Building @@ -199,16 +223,17 @@ A more comprehensive alternative is: make -j2 TILES=1 SOUND=1 RELEASE=1 USE_HOME_DIR=1 -The -j2 flag means it will compile with two parallel processes. It can be omitted or changed to -j4 in a more modern processor. If there is no desire to have sound, those flags can also be omitted. The USE_HOME_DIR flag places the user files, like configurations and saves into the home folder, making It easier for backups, and can also be omitted. - - +The -j2 flag means it will compile with two parallel processes. It can be omitted or changed to -j4 +in a more modern processor. If there is no desire to have sound, those flags can also be omitted. +The USE_HOME_DIR flag places the user files, like configurations and saves into the home folder, +making It easier for backups, and can also be omitted. ## Cross-compiling to linux 32-bit from linux 64-bit Dependencies: - * 32-bit toolchain - * 32-bit ncursesw (compatible with both multi-byte and 8-bit locales) +- 32-bit toolchain +- 32-bit ncursesw (compatible with both multi-byte and 8-bit locales) Install: @@ -221,9 +246,11 @@ Run: make NATIVE=linux32 ## Cross-compile to Windows from Linux + To cross-compile to Windows from Linux, you will need [MXE](http://mxe.cc). -These instructions were written for Ubuntu 20.04, but should be applicable to any Debian-based environment. Please adjust all package manager instructions to match your environment. +These instructions were written for Ubuntu 20.04, but should be applicable to any Debian-based +environment. Please adjust all package manager instructions to match your environment. MXE can be either installed from MXE apt repository (much faster) or compiled from source. @@ -234,7 +261,8 @@ MXE can be either installed from MXE apt repository (much faster) or compiled fr sudo apt-get update sudo apt-get install astyle bzip2 git make mxe-{i686,x86-64}-w64-mingw32.static-{sdl2,sdl2-ttf,sdl2-image,sdl2-mixer} -If you are not planning on building for both 32-bit and 64-bit, you might want to adjust the last apt-get invocation to install only `i686` or `x86-64` packages. +If you are not planning on building for both 32-bit and 64-bit, you might want to adjust the last +apt-get invocation to install only `i686` or `x86-64` packages. Edit your `~/.profile` as follows: @@ -244,6 +272,7 @@ Edit your `~/.profile` as follows: This is to ensure that the variables for the `make` command will not get reset after a power cycle. ### Installing MXE from source + Install [MXE requirements](http://mxe.cc/#requirements) and build dependencies: sudo apt install astyle autoconf automake autopoint bash bison bzip2 cmake flex gettext git g++ gperf intltool libffi-dev libgdk-pixbuf2.0-dev libtool libltdl-dev libssl-dev libxml-parser-perl lzip make mingw-w64 openssl p7zip-full patch perl pkg-config python ruby scons sed unzip wget xz-utils g++-multilib libc6-dev-i386 libtool-bin @@ -256,9 +285,11 @@ Clone MXE repo and build packages required for CBN: cd mxe make -j$((`nproc`+0)) MXE_TARGETS='x86_64-w64-mingw32.static i686-w64-mingw32.static' sdl2 sdl2_ttf sdl2_image sdl2_mixer -Building all these packages from MXE might take a while, even on a fast computer. Be patient; the `-j` flag will take advantage of all your processor cores. +Building all these packages from MXE might take a while, even on a fast computer. Be patient; the +`-j` flag will take advantage of all your processor cores. -If you are not planning on building for both 32-bit and 64-bit, you might want to adjust your MXE_TARGETS. +If you are not planning on building for both 32-bit and 64-bit, you might want to adjust your +MXE_TARGETS. Edit your `~/.profile` as follows: @@ -266,6 +297,7 @@ Edit your `~/.profile` as follows: export PLATFORM_64="~/src/mxe/usr/bin/x86_64-w64-mingw32.static-" This is to ensure that the variables for the `make` command will not get reset after a power cycle. + ### Building (SDL) Run one of the following commands based on your targeted environment: @@ -275,29 +307,34 @@ Run one of the following commands based on your targeted environment: ## Cross-compile to Mac OS X from Linux -The procedure is very much similar to cross-compilation to Windows from Linux. -Tested on ubuntu 14.04 LTS but should work on other distros as well. +The procedure is very much similar to cross-compilation to Windows from Linux. Tested on ubuntu +14.04 LTS but should work on other distros as well. + +Please note that due to historical difficulties with cross-compilation errors, run-time +optimizations are disabled for cross-compilation to Mac OS X targets. (`-O0` is specified as a +compilation flag.) See +[Pull Request #26564](https://github.com/CleverRaven/Cataclysm-DDA/pull/26564) for details. -Please note that due to historical difficulties with cross-compilation errors, run-time optimizations are disabled for cross-compilation to Mac OS X targets. (`-O0` is specified as a compilation flag.) See [Pull Request #26564](https://github.com/CleverRaven/Cataclysm-DDA/pull/26564) for details. ### Dependencies - * OSX cross-compiling toolchain [osxcross](https://github.com/tpoechtrager/osxcross) +- OSX cross-compiling toolchain [osxcross](https://github.com/tpoechtrager/osxcross) - * `genisoimage` and [libdmg-hfsplus](https://github.com/planetbeing/libdmg-hfsplus.git) to create dmg distributions +- `genisoimage` and [libdmg-hfsplus](https://github.com/planetbeing/libdmg-hfsplus.git) to create + dmg distributions Make sure that all dependency tools are in search `PATH` before compiling. ### Setup To set up the compiling environment execute the following commands -`git clone https://github.com/tpoechtrager/osxcross.git` to clone the toolchain -`cd osxcross` -`cp ~/MacOSX10.11.sdk.tar.bz2 ./tarballs/` copy prepared MacOSX SDK tarball on place. [Read more about it](https://github.com/tpoechtrager/osxcross/blob/master/README.md#packaging-the-sdk) -`OSX_VERSION_MIN=10.7 ./build.sh to build everything` -Note the targeted minimum supported version of OSX. +`git clone https://github.com/tpoechtrager/osxcross.git` to clone the toolchain `cd osxcross` +`cp ~/MacOSX10.11.sdk.tar.bz2 ./tarballs/` copy prepared MacOSX SDK tarball on place. +[Read more about it](https://github.com/tpoechtrager/osxcross/blob/master/README.md#packaging-the-sdk) +`OSX_VERSION_MIN=10.7 ./build.sh to build everything` Note the targeted minimum supported version of +OSX. -Have a prepackaged set of libs and frameworks in place, since compiling with `osxcross` built-in MacPorts is rather difficult and not supported at the moment. -Your directory tree should look like: +Have a prepackaged set of libs and frameworks in place, since compiling with `osxcross` built-in +MacPorts is rather difficult and not supported at the moment. Your directory tree should look like: ~/ ├── Frameworks @@ -310,10 +347,9 @@ Your directory tree should look like: ├── include └── lib -Populated with respective frameworks, dylibs and headers. -Tested with lib version libncurses.5.4.dylib for ncurses. -These libs were obtained from `homebrew` binary distribution at OS X 10.11 -Frameworks were obtained from SDL official website as described in the next [section](#sdl) +Populated with respective frameworks, dylibs and headers. Tested with lib version +libncurses.5.4.dylib for ncurses. These libs were obtained from `homebrew` binary distribution at OS +X 10.11 Frameworks were obtained from SDL official website as described in the next [section](#sdl) ### Building (SDL) @@ -336,17 +372,24 @@ Make sure that `x86_64-apple-darwin15-clang++` is in `PATH` environment variable ## Cross-compile to Android from Linux -The Android build uses [Gradle](https://gradle.org/) to compile the java and native C++ code, and is based heavily off SDL's [Android project template](https://hg.libsdl.org/SDL/file/f1084c419f33/android-project). See the official SDL documentation [README-android.md](https://hg.libsdl.org/SDL/file/f1084c419f33/docs/README-android.md) for further information. +The Android build uses [Gradle](https://gradle.org/) to compile the java and native C++ code, and is +based heavily off SDL's +[Android project template](https://hg.libsdl.org/SDL/file/f1084c419f33/android-project). See the +official SDL documentation +[README-android.md](https://hg.libsdl.org/SDL/file/f1084c419f33/docs/README-android.md) for further +information. -The Gradle project lives in the repository under `android/`. You can build it via the command line or open it in [Android Studio](https://developer.android.com/studio/). For simplicity, it only builds the SDL version with all features enabled, including tiles, sound and localization. +The Gradle project lives in the repository under `android/`. You can build it via the command line +or open it in [Android Studio](https://developer.android.com/studio/). For simplicity, it only +builds the SDL version with all features enabled, including tiles, sound and localization. ### Dependencies - * Java JDK 8 - * SDL2 (tested with 2.0.8, though a custom fork is recommended with project-specific bugfixes) - * SDL2_ttf (tested with 2.0.14) - * SDL2_mixer (tested with 2.0.2) - * SDL2_image (tested with 2.0.3) +- Java JDK 8 +- SDL2 (tested with 2.0.8, though a custom fork is recommended with project-specific bugfixes) +- SDL2_ttf (tested with 2.0.14) +- SDL2_mixer (tested with 2.0.2) +- SDL2_image (tested with 2.0.3) The Gradle build process automatically installs dependencies from [deps.zip](android/app/deps.zip). @@ -383,14 +426,18 @@ You can also use this additional variables if you want to use `ccache` to speed ### Android device setup -Enable [Developer options on your Android device](https://developer.android.com/studio/debug/dev-options). Connect your device to your PC via USB cable and run: +Enable +[Developer options on your Android device](https://developer.android.com/studio/debug/dev-options). +Connect your device to your PC via USB cable and run: adb devices adb connect ### Building -To build an APK, use the Gradle wrapper command line tool (gradlew). The Android Studio documentation provides a good summary of how to [build your app from the command line](https://developer.android.com/studio/build/building-cmdline). +To build an APK, use the Gradle wrapper command line tool (gradlew). The Android Studio +documentation provides a good summary of how to +[build your app from the command line](https://developer.android.com/studio/build/building-cmdline). To build a debug APK, from the `android/` subfolder of the repository run: @@ -402,15 +449,21 @@ To build a debug APK and immediately deploy to your connected device over adb ru ./gradlew installDebug -To build a signed release APK (ie. one that can be installed on a device), [build an unsigned release APK and sign it manually](https://developer.android.com/studio/publish/app-signing#signing-manually). +To build a signed release APK (ie. one that can be installed on a device), +[build an unsigned release APK and sign it manually](https://developer.android.com/studio/publish/app-signing#signing-manually). ### Additional notes -The app stores data files on the device in `/sdcard/Android/data/com.cleverraven/cataclysmdda/files`. The data is backwards compatible with the desktop version. +The app stores data files on the device in +`/sdcard/Android/data/com.cleverraven/cataclysmdda/files`. The data is backwards compatible with the +desktop version. # Mac OS X -To build Cataclysm on Mac you'll need [Command Line Tools for Xcode](https://developer.apple.com/downloads/) and the [Homebrew](http://brew.sh) package manager. With Homebrew, you can easily install or build Cataclysm using the [cataclysm](https://formulae.brew.sh/formula/cataclysm) forumla. +To build Cataclysm on Mac you'll need +[Command Line Tools for Xcode](https://developer.apple.com/downloads/) and the +[Homebrew](http://brew.sh) package manager. With Homebrew, you can easily install or build Cataclysm +using the [cataclysm](https://formulae.brew.sh/formula/cataclysm) forumla. ## Simple build using Homebrew @@ -422,11 +475,14 @@ For a stable tiles build: brew install cataclysm -For an experimental tiles build built from the current HEAD of [upload](https://github.com/cataclysmbnteam/Cataclysm-BN/tree/upload/): +For an experimental tiles build built from the current HEAD of +[upload](https://github.com/cataclysmbnteam/Cataclysm-BN/tree/upload/): brew install cataclysm --HEAD -Whichever build you choose, Homebrew will install the appropriate dependencies as needed. The installation will be in `/usr/local/Cellar/cataclysm` with a symlink named `cataclysm` in `/usr/local/bin`. +Whichever build you choose, Homebrew will install the appropriate dependencies as needed. The +installation will be in `/usr/local/Cellar/cataclysm` with a symlink named `cataclysm` in +`/usr/local/bin`. To launch Cataclysm, just open Terminal and run `cataclysm`. @@ -434,31 +490,35 @@ To update a stable tiles build simply run: brew upgrade cataclysm -To update an experimental build, you must uninstall Cataclysm then reinstall with `--HEAD`, triggering a new build from source. +To update an experimental build, you must uninstall Cataclysm then reinstall with `--HEAD`, +triggering a new build from source. brew uninstall cataclysm brew install cataclysm --HEAD ## Advanced info for Developers -For most people, the simple Homebrew installation is enough. For developers, here are some more technical details on building Cataclysm on Mac OS X. +For most people, the simple Homebrew installation is enough. For developers, here are some more +technical details on building Cataclysm on Mac OS X. ### SDL -SDL2, SDL2_image, and SDL2_ttf are needed for the tiles build. Optionally, you can add SDL2_mixer for sound support. Cataclysm can be built using either the SDL framework, or shared libraries built from source. +SDL2, SDL2_image, and SDL2_ttf are needed for the tiles build. Optionally, you can add SDL2_mixer +for sound support. Cataclysm can be built using either the SDL framework, or shared libraries built +from source. The SDL framework files can be downloaded here: -* [**SDL2**](http://www.libsdl.org/download-2.0.php) -* [**SDL2_image**](http://www.libsdl.org/projects/SDL_image/) -* [**SDL2_ttf**](http://www.libsdl.org/projects/SDL_ttf/) +- [**SDL2**](http://www.libsdl.org/download-2.0.php) +- [**SDL2_image**](http://www.libsdl.org/projects/SDL_image/) +- [**SDL2_ttf**](http://www.libsdl.org/projects/SDL_ttf/) -Copy `SDL2.framework`, `SDL2_image.framework`, and `SDL2_ttf.framework` -to `/Library/Frameworks` or `/Users/name/Library/Frameworks`. +Copy `SDL2.framework`, `SDL2_image.framework`, and `SDL2_ttf.framework` to `/Library/Frameworks` or +`/Users/name/Library/Frameworks`. If you want sound support, you will need an additional SDL framework: -* [**SDL2_mixer**](https://www.libsdl.org/projects/SDL_mixer/) +- [**SDL2_mixer**](https://www.libsdl.org/projects/SDL_mixer/) Copy `SDL2_mixer.framework` to `/Library/Frameworks` or `/Users/name/Library/Frameworks`. @@ -482,7 +542,8 @@ with sound: ### ncurses -ncurses with wide character support enabled is needed since Cataclysm makes extensive use of Unicode characters +ncurses with wide character support enabled is needed since Cataclysm makes extensive use of Unicode +characters For Homebrew: @@ -495,11 +556,17 @@ For MacPorts: ### gcc -The version of gcc/g++ installed with the [Command Line Tools for Xcode](https://developer.apple.com/downloads/) is actually just a front end for the same Apple LLVM as clang. This doesn't necessarily cause issues, but this version of gcc/g++ will have clang error messages and essentially produce the same results as if using clang. To compile with the "real" gcc/g++, install it with homebrew: +The version of gcc/g++ installed with the +[Command Line Tools for Xcode](https://developer.apple.com/downloads/) is actually just a front end +for the same Apple LLVM as clang. This doesn't necessarily cause issues, but this version of gcc/g++ +will have clang error messages and essentially produce the same results as if using clang. To +compile with the "real" gcc/g++, install it with homebrew: brew install gcc -However, homebrew installs gcc as gcc-{version} (where {version} is the version) to avoid conflicts. The simplest way to use the homebrew version at `/usr/local/bin/gcc-{version}` instead of the Apple LLVM version at `/usr/bin/gcc` is to symlink the necessary. +However, homebrew installs gcc as gcc-{version} (where {version} is the version) to avoid conflicts. +The simplest way to use the homebrew version at `/usr/local/bin/gcc-{version}` instead of the Apple +LLVM version at `/usr/bin/gcc` is to symlink the necessary. cd /usr/local/bin ln -s gcc-12 gcc @@ -510,7 +577,8 @@ Or, to do this for everything in `/usr/local/bin/` ending with `-12`, find /usr/local/bin -name "*-12" -exec sh -c 'ln -s "$1" $(echo "$1" | sed "s/..$//")' _ {} \; -Also, you need to make sure that `/usr/local/bin` appears before `/usr/bin` in your `$PATH`, or else this will not work. +Also, you need to make sure that `/usr/local/bin` appears before `/usr/bin` in your `$PATH`, or else +this will not work. Check that `gcc -v` shows the homebrew version you installed. @@ -520,19 +588,28 @@ The Cataclysm source is compiled using `make`. ### Make options -* `NATIVE=osx` build for OS X. Required for all Mac builds. -* `OSX_MIN=version` sets `-mmacosx-version-min=`; default is 11. -* `TILES=1` build the SDL version with graphical tiles (and graphical ASCII); omit to build with `ncurses`. -* `SOUND=1` - if you want sound; this requires `TILES=1` and the additional dependencies mentioned above. -* `FRAMEWORK=1` (tiles only) link to SDL libraries under the OS X Frameworks folders; omit to use SDL shared libraries from Homebrew or Macports. -* `LANGUAGES="[lang_id_2][...]"` compile localization files for specified languages. e.g. `LANGUAGES="zh_CN zh_TW"`. You can also use `LANGUAGES=all` to compile all localization files. -* `RELEASE=1` build an optimized release version; omit for debug build. -* `CLANG=1` build with [Clang](http://clang.llvm.org/), the compiler that's included with the latest Command Line Tools for Xcode; omit to build using gcc/g++. -* `MACPORTS=1` build against dependencies installed via Macports, currently only `ncurses`. -* `USE_HOME_DIR=1` places user files (config, saves, graveyard, etc) in the user's home directory. For curses builds, this is `/Users//.cataclysm-bn`, for SDL builds it is `/Users//Library/Application Support/Cataclysm`. -* `DEBUG_SYMBOLS=1` retains debug symbols when building an optimized release binary, making it easy for developers to spot the crash site. - -In addition to the options above, there is an `app` make target which will package the tiles build into `Cataclysm.app`, a complete tiles build in a Mac application that can run without Terminal. +- `NATIVE=osx` build for OS X. Required for all Mac builds. +- `OSX_MIN=version` sets `-mmacosx-version-min=`; default is 11. +- `TILES=1` build the SDL version with graphical tiles (and graphical ASCII); omit to build with + `ncurses`. +- `SOUND=1` - if you want sound; this requires `TILES=1` and the additional dependencies mentioned + above. +- `FRAMEWORK=1` (tiles only) link to SDL libraries under the OS X Frameworks folders; omit to use + SDL shared libraries from Homebrew or Macports. +- `LANGUAGES="[lang_id_2][...]"` compile localization files for specified languages. e.g. + `LANGUAGES="zh_CN zh_TW"`. You can also use `LANGUAGES=all` to compile all localization files. +- `RELEASE=1` build an optimized release version; omit for debug build. +- `CLANG=1` build with [Clang](http://clang.llvm.org/), the compiler that's included with the latest + Command Line Tools for Xcode; omit to build using gcc/g++. +- `MACPORTS=1` build against dependencies installed via Macports, currently only `ncurses`. +- `USE_HOME_DIR=1` places user files (config, saves, graveyard, etc) in the user's home directory. + For curses builds, this is `/Users//.cataclysm-bn`, for SDL builds it is + `/Users//Library/Application Support/Cataclysm`. +- `DEBUG_SYMBOLS=1` retains debug symbols when building an optimized release binary, making it easy + for developers to spot the crash site. + +In addition to the options above, there is an `app` make target which will package the tiles build +into `Cataclysm.app`, a complete tiles build in a Mac application that can run without Terminal. For more info, see the comments in the `Makefile`. @@ -542,7 +619,8 @@ Build a release SDL version using Clang: make NATIVE=osx RELEASE=1 TILES=1 CLANG=1 -Build a release SDL version using Clang, link to libraries in the OS X Frameworks folders, build all language files, and package it into `Cataclysm.app`: +Build a release SDL version using Clang, link to libraries in the OS X Frameworks folders, build all +language files, and package it into `Cataclysm.app`: make app NATIVE=osx RELEASE=1 TILES=1 FRAMEWORK=1 LANGUAGES=all CLANG=1 @@ -564,20 +642,26 @@ For `app` builds, launch Cataclysm.app from Finder. ### Test suite -The build will also generate a test executable at tests/cata_test. -Invoke it as you would any other executable and it will run the full suite of tests. -Pass the ``--help`` flag to list options. +The build will also generate a test executable at tests/cata_test. Invoke it as you would any other +executable and it will run the full suite of tests. Pass the `--help` flag to list options. ### dmg distribution -You can build a nice dmg distribution file with the `dmgdist` target. You will need a tool called [dmgbuild](https://pypi.python.org/pypi/dmgbuild). To install this tool, you will need Python first. If you are on Mac OS X >= 10.8, Python 2.7 is pre-installed with the OS. If you are on an older version of OS X, you can download Python [on their official website](https://www.python.org/downloads/) or install it with homebrew `brew install python`. Once you have Python, you should be able to install `dmgbuild` by running: +You can build a nice dmg distribution file with the `dmgdist` target. You will need a tool called +[dmgbuild](https://pypi.python.org/pypi/dmgbuild). To install this tool, you will need Python first. +If you are on Mac OS X >= 10.8, Python 2.7 is pre-installed with the OS. If you are on an older +version of OS X, you can download Python +[on their official website](https://www.python.org/downloads/) or install it with homebrew +`brew install python`. Once you have Python, you should be able to install `dmgbuild` by running: # This install pip. It might not be required if it is already installed. curl --silent --show-error --retry 5 https://bootstrap.pypa.io/get-pip.py | sudo python # dmgbuild install sudo pip install dmgbuild pyobjc-framework-Quartz -Once `dmgbuild` is installed, you will be able to use the `dmgdist` target like this. The use of `USE_HOME_DIR=1` is important here because it will allow for an easy upgrade of the game while keeping the user config and his saves in his home directory. +Once `dmgbuild` is installed, you will be able to use the `dmgdist` target like this. The use of +`USE_HOME_DIR=1` is important here because it will allow for an easy upgrade of the game while +keeping the user config and his saves in his home directory. make dmgdist NATIVE=osx RELEASE=1 TILES=1 FRAMEWORK=1 CLANG=1 USE_HOME_DIR=1 @@ -587,38 +671,54 @@ You should see a `Cataclysm.dmg` file. ### ISSUE: Colors don't show up correctly -Open Terminal's preferences, turn on "Use bright colors for bold text" in "Preferences -> Settings -> Text" - +Open Terminal's preferences, turn on "Use bright colors for bold text" in "Preferences -> Settings +-> Text" # Windows -See [COMPILING-VS-VCPKG.md](COMPILING-VS-VCPKG.md) for instructions on how to set up and use a build environment using Visual Studio on windows. +See [COMPILING-VS-VCPKG.md](COMPILING-VS-VCPKG.md) for instructions on how to set up and use a build +environment using Visual Studio on windows. -This is probably the easiest solution for someone used to working with Visual Studio and similar IDEs. --> +This is probably the easiest solution for someone used to working with Visual Studio and similar +IDEs. --> ## Building with MSYS2 -See [COMPILING-MSYS.md](COMPILING-MSYS.md) for instructions on how to set up and use a build environment using MSYS2 on windows. +See [COMPILING-MSYS.md](COMPILING-MSYS.md) for instructions on how to set up and use a build +environment using MSYS2 on windows. -MSYS2 strikes a balance between a native Windows application and a UNIX-like environment. There's some command-line tools that our project uses (notably our JSON linter) that are harder to use without a command-line environment such as what MSYS2 or CYGWIN provide. +MSYS2 strikes a balance between a native Windows application and a UNIX-like environment. There's +some command-line tools that our project uses (notably our JSON linter) that are harder to use +without a command-line environment such as what MSYS2 or CYGWIN provide. ## Building with CYGWIN -See [COMPILING-CYGWIN.md](COMPILING-CYGWIN.md) for instructions on how to set up and use a build environment using CYGWIN on windows. +See [COMPILING-CYGWIN.md](COMPILING-CYGWIN.md) for instructions on how to set up and use a build +environment using CYGWIN on windows. -CYGWIN attempts to more fully emulate a POSIX environment, to be "more unix" than MSYS2. It is a little less modern in some respects, and lacks the convenience of the MSYS2 package manager. +CYGWIN attempts to more fully emulate a POSIX environment, to be "more unix" than MSYS2. It is a +little less modern in some respects, and lacks the convenience of the MSYS2 package manager. ## Building with Clang and MinGW64 -Clang by default uses MSVC on Windows, but also supports the MinGW64 library. Simply replace `CLANG=1` with `"CLANG=clang++ -target x86_64-pc-windows-gnu -pthread"` in your batch script, and make sure MinGW64 is in your path. You may also need to apply [a patch](https://sourceforge.net/p/mingw-w64/mailman/message/36386405/) to `float.h` of MinGW64 for the unit test to compile. +Clang by default uses MSVC on Windows, but also supports the MinGW64 library. Simply replace +`CLANG=1` with `"CLANG=clang++ -target x86_64-pc-windows-gnu -pthread"` in your batch script, and +make sure MinGW64 is in your path. You may also need to apply +[a patch](https://sourceforge.net/p/mingw-w64/mailman/message/36386405/) to `float.h` of MinGW64 for +the unit test to compile. # BSDs -There are reports of CBN building fine on recent OpenBSD and FreeBSD machines (with appropriately recent compilers), and there is some work being done on making the `Makefile` "just work", however we're far from that and BSDs support is mostly based on user contributions. Your mileage may vary. So far essentially all testing has been on amd64, but there is no (known) reason that other architectures shouldn't work, in principle. +There are reports of CBN building fine on recent OpenBSD and FreeBSD machines (with appropriately +recent compilers), and there is some work being done on making the `Makefile` "just work", however +we're far from that and BSDs support is mostly based on user contributions. Your mileage may vary. +So far essentially all testing has been on amd64, but there is no (known) reason that other +architectures shouldn't work, in principle. ### Building on FreeBSD/amd64 10.1 with the system compiler -FreeBSD uses clang as the default compiler as of 10.0, and combines it with libc++ to provide C++14 support out of the box. You will however need gmake (examples for binary packages): +FreeBSD uses clang as the default compiler as of 10.0, and combines it with libc++ to provide C++14 +support out of the box. You will however need gmake (examples for binary packages): `pkg install gmake` @@ -626,7 +726,8 @@ Tiles builds will also require SDL2: `pkg install sdl2 sdl2_image sdl2_mixer sdl2_ttf` -Then you should be able to build with something like this (you can of course set CXXFLAGS and LDFLAGS in your .profile or something): +Then you should be able to build with something like this (you can of course set CXXFLAGS and +LDFLAGS in your .profile or something): ``` export CXXFLAGS="-I/usr/local/include" LDFLAGS="-L/usr/local/lib" @@ -634,7 +735,8 @@ gmake # ncurses builds gmake TILES=1 # tiles builds ``` -The author has not tested tiles builds, as the build VM lacks X; they do at least compile/link successfully. +The author has not tested tiles builds, as the build VM lacks X; they do at least compile/link +successfully. ### Building ncurses version on FreeBSD/amd64 9.3 with GCC 4.8.4 from ports @@ -646,21 +748,24 @@ CXX = g++48 CXXFLAGS += -I/usr/local/lib/gcc48/include LDFLAGS += -rpath=/usr/local/lib/gcc48 ``` + Note: or you can `setenv` the above (merging `OTHERS` into `CXXFLAGS`), but you knew that. And then build with `gmake RELEASE=1`. ### Building on OpenBSD/amd64 5.8 with GCC 4.9.2 from ports/packages -First, install g++, gmake, and libexecinfo from packages (g++ 4.8 or 4.9 should work; 4.9 has been tested): +First, install g++, gmake, and libexecinfo from packages (g++ 4.8 or 4.9 should work; 4.9 has been +tested): `pkg_add g++ gmake libexecinfo` -Then you should be able to build with something like: +Then you should be able to build with something like: `CXX=eg++ gmake` -Only an ncurses build is possible on 5.8-release, as SDL2 is broken. On recent -current or snapshots, however, you can install the SDL2 packages: +Only an ncurses build is possible on 5.8-release, as SDL2 is broken. On recent -current or +snapshots, however, you can install the SDL2 packages: `pkg_add sdl2 sdl2-image sdl2-mixer sdl2-ttf` @@ -670,11 +775,14 @@ and build with: ### Building on NetBSD/amd64 7.0RC1 with the system compiler -NetBSD has (or will have) gcc 4.8.4 as of version 7.0, which is new enough to build cataclysm. You will need to install gmake and ncursesw: +NetBSD has (or will have) gcc 4.8.4 as of version 7.0, which is new enough to build cataclysm. You +will need to install gmake and ncursesw: `pkgin install gmake ncursesw` -Then you should be able to build with something like this (LDFLAGS for ncurses builds are taken care of by the ncurses configuration script; you can of course set CXXFLAGS/LDFLAGS in your .profile or something): +Then you should be able to build with something like this (LDFLAGS for ncurses builds are taken care +of by the ncurses configuration script; you can of course set CXXFLAGS/LDFLAGS in your .profile or +something): ``` export CXXFLAGS="-I/usr/pkg/include" @@ -682,4 +790,5 @@ gmake # ncurses builds LDFLAGS="-L/usr/pkg/lib" gmake TILES=1 # tiles builds ``` -SDL builds currently compile, but did not run in my testing - not only do they segfault, but gdb segfaults when reading the debug symbols! Perhaps your mileage will vary. +SDL builds currently compile, but did not run in my testing - not only do they segfault, but gdb +segfaults when reading the debug symbols! Perhaps your mileage will vary. diff --git a/doc/CONTRIBUTING.ko.md b/doc/CONTRIBUTING.ko.md index ba7f538b4bf2..f23090e04480 100644 --- a/doc/CONTRIBUTING.ko.md +++ b/doc/CONTRIBUTING.ko.md @@ -1,7 +1,6 @@ # 기여하기 -[![en][icon-en]][en] -[![ko][icon-ko]][ko] +[![en][icon-en]][en] [![ko][icon-ko]][ko] [en]: ./CONTRIBUTING.md [icon-en]: https://img.shields.io/badge/lang-en-red?style=flat-square @@ -11,6 +10,9 @@ - [기여하기](#기여하기) - [가이드라인](#가이드라인) - [코드 스타일](#코드-스타일) + - [C++](#c) + - [JSON 스타일](#json-스타일) + - [마크다운](#마크다운) - [번역](#번역) - [공식 문서](#공식-문서) - [독시젠(Doxygen) 주석](#독시젠doxygen-주석) @@ -44,15 +46,18 @@ [pr]: https://docs.github.com/ko/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests -> 카타클리즘: 밝은 밤은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 3.0 라이선스에 따라 배포됩니다. 게임의 코드와 콘텐츠는 어떠한 목적에도 사용, 수정, 재배포할 수 있습니다. 자세한 내용은 http://creativecommons.org/licenses/by-sa/3.0/ 를 참고해주세요. -> 그 말은, 이 프로젝트에 기여하면, 그 기여물도 동일한 라이선스에 의해 보호받는다는 것이며, 이 라이선스는 취소될 수 없다는 것입니다. +> 카타클리즘: 밝은 밤은 크리에이티브 커먼즈 저작자표시-동일조건변경허락 3.0 라이선스에 따라 +> 배포됩니다. 게임의 코드와 콘텐츠는 어떠한 목적에도 사용, 수정, 재배포할 수 있습니다. 자세한 내용은 +> http://creativecommons.org/licenses/by-sa/3.0/ 를 참고해주세요. 그 말은, 이 프로젝트에 기여하면, +> 그 기여물도 동일한 라이선스에 의해 보호받는다는 것이며, 이 라이선스는 취소될 수 없다는 것입니다. ## 가이드라인 몇 가지 지켰으면 하는 가이드라인이 있습니다: - 이 저장소를 `upstream` [리모트][remote]로 추가해주세요. -- `upload` 브랜치를 수정사항 없이 깨끗하게 유지해주세요. 원격 저장소의 최신 변경사항을 바로 끌어올 수 있게 하기 위함입니다. +- `upload` 브랜치를 수정사항 없이 깨끗하게 유지해주세요. 원격 저장소의 최신 변경사항을 바로 끌어올 + 수 있게 하기 위함입니다. - 새 기능이나 버그 수정을 할 때마다 새 브랜치를 만들어주세요. - 절대로 `upload` 브랜치에 로컬 브랜치를 병합하지 마세요. `upstream/upload`에서 끌어오기만 해주세요. @@ -60,13 +65,37 @@ ## 코드 스타일 -`astyle`로 일관된 코드 스타일을 강제하고 있습니다. -자세한 내용은 [CODE_STYLE](../doc/CODE_STYLE.md)을 참고해주세요. +### C++ + +`astyle`로 일관된 코드 스타일을 강제하고 있습니다. 자세한 내용은 +[CODE_STYLE](../doc/CODE_STYLE.md)을 참고해주세요. + +### JSON 스타일 + +`tools/format` 경로에 있는 포매터로 일관된 JSON 스타일을 강제하고 있습니다. +[JSON Style Guide](../doc/JSON_STYLE.md) 을 참고해주세요. + +### 마크다운 + +`doc/`같은 마크다운 파일들은 [`deno`](https://deno.com)를 사용해 포매팅하고 있습니다. +[`deno fmt`](https://deno.land/manual/tools/formatter) 을 실행해 자동으로 마크다운 파일을 +포매팅하세요. VsCode를 사용중이라면 다음 설정으로 저장할 때마다 자동 포매팅을 실행할 수 있습니다: + +```json +// .vscode/settings.json +{ + "[markdown]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "denoland.vscode-deno" + } +} +``` ## 번역 카타클리즘: 밝은 밤의 번역은 Transifex에서 진행중입니다. -[번역 프로젝트](https://app.transifex.com/bn-team/cataclysm-bright-nights/)에서 지원되는 언어를 실시간으로 확인할 수 있습니다. +[번역 프로젝트](https://app.transifex.com/bn-team/cataclysm-bright-nights/)에서 지원되는 언어를 +실시간으로 확인할 수 있습니다. [TRANSLATING](../doc/TRANSLATING.md)에서 더 자세한 내용을 확인할 수 있습니다: @@ -81,11 +110,13 @@

-자동 생성된 문서를 [깃허브 페이지](https://cataclysmbnteam.github.io/Cataclysm-BN)에서 읽을 수 있습니다. +자동 생성된 문서를 [깃허브 페이지](https://cataclysmbnteam.github.io/Cataclysm-BN)에서 읽을 수 +있습니다. ### 독시젠(Doxygen) 주석 -클래스와 클래스 멤버에 대한 상세한 문서가 있으면 새로운 기여자들이 코드를 읽고 이해하는데 도움이 됩니다. 기존 클래스에 독시젠 주석을 다는 것도 환영입니다. +클래스와 클래스 멤버에 대한 상세한 문서가 있으면 새로운 기여자들이 코드를 읽고 이해하는데 도움이 +됩니다. 기존 클래스에 독시젠 주석을 다는 것도 환영입니다. 클래스에 주석을 달 때는 다음 템플릿을 사용해주세요: @@ -120,15 +151,18 @@ int foo; ### 문서 추가 가이드라인 -- 독시젠 주석은 '밖에서 보았을 때' 동작을 설명해야 합니다. 숨겨진 내부 구현에 대한 설명은 하지 말아야 합니다. 하지만 카타클리즘의 많은 클래스들이 서로 연결되어 있어서, 구현에 대한 설명이 필요할 때도 있을 것입니다. +- 독시젠 주석은 '밖에서 보았을 때' 동작을 설명해야 합니다. 숨겨진 내부 구현에 대한 설명은 하지 + 말아야 합니다. 하지만 카타클리즘의 많은 클래스들이 서로 연결되어 있어서, 구현에 대한 설명이 필요할 + 때도 있을 것입니다. - 새 기여자들이 이름만으로는 이해하기 어려운 것들에 대해서만 설명해주세요. - 동어 반복은 피해주세요: `/** Map **/; map* map;`는 도움이 되지 않습니다. -- `X`에 대한 설명을 할 때, `X`와 다른 컴포넌트들 간의 상호작용에 대해서만 설명해주세요. `X` 자체가 하는 일에 대해서는 설명하지 말아주세요. +- `X`에 대한 설명을 할 때, `X`와 다른 컴포넌트들 간의 상호작용에 대해서만 설명해주세요. `X` 자체가 + 하는 일에 대해서는 설명하지 말아주세요. ### 문서를 로컬에서 빌드하기 - [독시젠 설치](https://www.doxygen.nl) -- `doxygen doxygen_doc/doxygen_conf.txt ` +- `doxygen doxygen_doc/doxygen_conf.txt` - `firefox doxygen_doc/html/index.html` (또는 다른 브라우저) ## 예시 워크플로우 @@ -149,7 +183,7 @@ $ git clone https://github.com/깃허브_사용자명/Cataclysm-BN.git 3. 커밋 메시지 템플릿을 설정합니다. ```sh - $ git config --local commit.template .gitmessage +$ git config --local commit.template .gitmessage ``` 4. 원본 저장소를 원격 저장소로 추가합니다. @@ -182,7 +216,8 @@ $ git pull --ff-only upstream upload # "upstream" 원격 저장소의 "upload" 브랜치에서 변경사항을 가져옵니다. ``` -> **Note** 오류가 발생했다면, 로컬 `upload` 브랜치에 직접 커밋을 했다는 뜻입니다. [이 문제를 해결하는 방법을 보려면 여기를 클릭하세요](#git-pull---ff-only을-했더니-에러가-나요). +> **Note** 오류가 발생했다면, 로컬 `upload` 브랜치에 직접 커밋을 했다는 뜻입니다. +> [이 문제를 해결하는 방법을 보려면 여기를 클릭하세요](#git-pull---ff-only을-했더니-에러가-나요). ### 변경사항 만들기 @@ -204,28 +239,38 @@ $ git push origin new_feature # origin은 복제할 때 자동으로 포크를 가리키도록 설정되어 있습니다. ``` -3. 브랜치에서 작업을 마치고, 모든 변경사항을 커밋하고 푸시했다면, `new_feature` 브랜치에서 이 저장소의 `upload` 브랜치로 풀 리퀘스트를 보내주세요. +3. 브랜치에서 작업을 마치고, 모든 변경사항을 커밋하고 푸시했다면, `new_feature` 브랜치에서 이 + 저장소의 `upload` 브랜치로 풀 리퀘스트를 보내주세요. -> **Note** 깃허브의 `new_feature` 브랜치에 새 커밋이 생기면, 풀 리퀘스트에 자동으로 포함됩니다. 따라서 같은 브랜치에 관련된 변경사항만 커밋해주세요. +> **Note** 깃허브의 `new_feature` 브랜치에 새 커밋이 생기면, 풀 리퀘스트에 자동으로 포함됩니다. +> 따라서 같은 브랜치에 관련된 변경사항만 커밋해주세요. ## 풀 리퀘스트 초안 -풀 리퀘스트를 만들었지만 아직 작업 중이라면, [초안(draft)](https://docs.github.com/ko/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests)으로 표시해주세요. 이렇게 하면 준비된 상태가 아니라는 것을 리뷰어에게 알려줘 리뷰 진행 속도를 높일 수 있습니다. +풀 리퀘스트를 만들었지만 아직 작업 중이라면, +[초안(draft)](https://docs.github.com/ko/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests)으로 +표시해주세요. 이렇게 하면 준비된 상태가 아니라는 것을 리뷰어에게 알려줘 리뷰 진행 속도를 높일 수 +있습니다. -풀 리퀘스트를 만들 때 이슈를 참조할 필요는 없지만, 참조하지 않느나면 PR이 어떤 문제룰 해결하려는지 자세히 설명해야 합니다. +풀 리퀘스트를 만들 때 이슈를 참조할 필요는 없지만, 참조하지 않느나면 PR이 어떤 문제룰 해결하려는지 +자세히 설명해야 합니다. ### 모든 풀 리퀘스트에는 `"Summary"`줄이 있어야 합니다. -개요(summary)는 [변경 내역](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/data/changelog.txt)에 추가할 한 줄 요약입니다. +개요(summary)는 +[변경 내역](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/data/changelog.txt)에 추가할 +한 줄 요약입니다. 개요 형식: `SUMMARY: 카테고리 "설명"` -고를 수 있는 카테고리는 Features, Content, Interface, Mods, Balance, Bugfixes, Performance, Infrastructure, Build, I18N이 있습니다. +고를 수 있는 카테고리는 Features, Content, Interface, Mods, Balance, Bugfixes, Performance, +Infrastructure, Build, I18N이 있습니다. -예시: `SUMMARY: Content "Adds new mutation category 'Mouse'"` -(해석: `SUMMARY: Content "새로운 변이 카테고리 'Mouse'를 추가합니다."`) +예시: `SUMMARY: Content "Adds new mutation category 'Mouse'"` (해석: +`SUMMARY: Content "새로운 변이 카테고리 'Mouse'를 추가합니다."`) -[변경 내역 가이드라인](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/doc/CHANGELOG_GUIDELINES.md)에서 카테고리에 대한 설명을 볼 수 있습니다. +[변경 내역 가이드라인](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/doc/CHANGELOG_GUIDELINES.md)에서 +카테고리에 대한 설명을 볼 수 있습니다. ### 키워드로 이슈 닫기 @@ -257,11 +302,14 @@ $ git push origin new_feature - {키워드} #{이슈 번호}, {키워드} #{이슈 번호} ``` -더 자세한 설명은 [깃허브 공식 문서](https://docs.github.com/ko/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)를 참고해주세요. +더 자세한 설명은 +[깃허브 공식 문서](https://docs.github.com/ko/issues/tracking-your-work-with-issues/linking-a-pull-request-to-an-issue)를 +참고해주세요. ## 개발 도구 지원 -코딩 스타일을 지키도록 도와주는 여러 도구들이 있습니다. 자세한 내용은 [DEVELOPER_TOOLING](../doc/DEVELOPER_TOOLING.md)을 참고해주세요. +코딩 스타일을 지키도록 도와주는 여러 도구들이 있습니다. 자세한 내용은 +[DEVELOPER_TOOLING](../doc/DEVELOPER_TOOLING.md)을 참고해주세요. ## 고급 @@ -269,8 +317,9 @@ $ git push origin new_feature ### 원격 추적 브랜치 사용하기 -Remote tracking branches allow you to easily stay in touch with this repository's `upload` branch, as they automatically know which remote branch to get changes from. -원본 저장소의 `upload` 브랜치에 대한 원격 추적 브랜치를 설정하면 쉽게 최신 변경사항을 가져올 수 있습니다. +Remote tracking branches allow you to easily stay in touch with this repository's `upload` branch, +as they automatically know which remote branch to get changes from. 원본 저장소의 `upload` 브랜치에 +대한 원격 추적 브랜치를 설정하면 쉽게 최신 변경사항을 가져올 수 있습니다. ```sh $ git branch -vv @@ -278,7 +327,9 @@ $ git branch -vv new_feature xxxx .... ``` -`upload` 브랜치는 `origin/upload` 브랜치를 추적하고 있고, `new_feature` 브랜치는 아무 브랜치도 추적하고 있지 않습니다. 그 말은 git이 어디에서 `new_feature` 에 대한 변경사항을 가져올지 모른다는 뜻입니다. +`upload` 브랜치는 `origin/upload` 브랜치를 추적하고 있고, `new_feature` 브랜치는 아무 브랜치도 +추적하고 있지 않습니다. 그 말은 git이 어디에서 `new_feature` 에 대한 변경사항을 가져올지 모른다는 +뜻입니다. ```sh $ git checkout new_feature @@ -288,7 +339,8 @@ $ git pull 어떤 브랜치를 대상으로 병합할지 지정하십시오. ``` -`new_feature` 브랜치에서 `upstream/upload` 브랜치의 변경사항을 쉽게 가져오려면, git에 어떤 브랜치를 추적할지 알려줘야 합니다. (로컬 `upload` 브랜치에도 적용할 수 있습니다.) +`new_feature` 브랜치에서 `upstream/upload` 브랜치의 변경사항을 쉽게 가져오려면, git에 어떤 브랜치를 +추적할지 알려줘야 합니다. (로컬 `upload` 브랜치에도 적용할 수 있습니다.) ```sh $ git branch -u upstream/upload new_feature @@ -305,7 +357,9 @@ $ git branch new_feature_2 --track upstream/upload Branch new_feature_2 set up to track remote branch upload from upstream. ``` -> **Note** : 이렇게 하면 `upstream/upload` 브랜치에서 변경사항을 가져오는 것은 쉬워지지만, `git push`는 여전히 실패합니다. `git push`는 `upstream/upload` 브랜치에 변경사항을 푸시할 권한이 없기 때문입니다. +> **Note** : 이렇게 하면 `upstream/upload` 브랜치에서 변경사항을 가져오는 것은 쉬워지지만, +> `git push`는 여전히 실패합니다. `git push`는 `upstream/upload` 브랜치에 변경사항을 푸시할 권한이 +> 없기 때문입니다. ```sh $ git push @@ -319,8 +373,10 @@ xxxx..xxxx new_feature -> new_feature ## 단위 테스트 -`tests/` 경로에 단위 테스트가 있습니다. 게임 소스를 변경한 후에는 반드시 테스트를 실행해야 합니다. `make` 명령을 실행하면 `tests/cata_test` 실행 파일이 생성됩니다. 이 파일은 일반적인 실행 파일처럼 실행할 수 있습니다. `make check` 명령으로도 실행할 수 있습니다. -아무 인자 없이 실행하면 전체 테스트를 실행합니다. `--help` 인자를 사용하면 실행 옵션을 볼 수 있습니다. +`tests/` 경로에 단위 테스트가 있습니다. 게임 소스를 변경한 후에는 반드시 테스트를 실행해야 합니다. +`make` 명령을 실행하면 `tests/cata_test` 실행 파일이 생성됩니다. 이 파일은 일반적인 실행 파일처럼 +실행할 수 있습니다. `make check` 명령으로도 실행할 수 있습니다. 아무 인자 없이 실행하면 전체 +테스트를 실행합니다. `--help` 인자를 사용하면 실행 옵션을 볼 수 있습니다. ```sh $ make @@ -337,9 +393,13 @@ The test took 41.772 seconds ## 게임 내에서 테스트하기, 테스트 환경, 디버그 메뉴 -새 기능을 구현하거나 버그를 수정하는 경우, 게임 내에서 변경사항을 테스트하는 것이 좋습니다. 평소처럼 게임을 플레이해서 정확한 조건을 만들어내기는 힘들지만, 디버그 메뉴를 사용하면 쉽게 테스트할 수 있습니다. 기본적으로 메뉴를 띄우는 단축키가 없으므로 먼저 단축키를 지정해야 합니다. +새 기능을 구현하거나 버그를 수정하는 경우, 게임 내에서 변경사항을 테스트하는 것이 좋습니다. 평소처럼 +게임을 플레이해서 정확한 조건을 만들어내기는 힘들지만, 디버그 메뉴를 사용하면 쉽게 테스트할 수 +있습니다. 기본적으로 메뉴를 띄우는 단축키가 없으므로 먼저 단축키를 지정해야 합니다. -단축키 설정 메뉴를 띄웁니다. (`Esc`키를 누른 다음 `1`키를 누릅니다.) 아래로 스크롤해서 _디버그 메뉴_ 항목을 찾고, `+` 키를 눌러 새로운 단축키를 추가합니다. 테스트를 한 다면 새 캐릭터로 하는 것이 좋습니다. 방금 설정한 단축키를 누르면 다음과 같은 화면이 나타날 것입니다. +단축키 설정 메뉴를 띄웁니다. (`Esc`키를 누른 다음 `1`키를 누릅니다.) 아래로 스크롤해서 _디버그 메뉴_ +항목을 찾고, `+` 키를 눌러 새로운 단축키를 추가합니다. 테스트를 한 다면 새 캐릭터로 하는 것이 +좋습니다. 방금 설정한 단축키를 누르면 다음과 같은 화면이 나타날 것입니다. ``` ┌─────────────────────────────────────────────────────┐ @@ -354,13 +414,17 @@ The test took 41.772 seconds └─────────────────────────────────────────────────────┘ ``` -위 명령어들을 사용해서 변경사항을 테스트할 수 있습니다. [DDA 위키](http://cddawiki.chezzo.com/cdda_wiki/index.php)에도 디버그 메뉴에 대한 정보가 있습니다. +위 명령어들을 사용해서 변경사항을 테스트할 수 있습니다. +[DDA 위키](http://cddawiki.chezzo.com/cdda_wiki/index.php)에도 디버그 메뉴에 대한 정보가 있습니다. ## 자주 묻는 질문 ### `git pull --ff-only`을 했더니 에러가 나요 -`git pull --ff-only`를 실행했더니 에러가 났다면, `upload` 브랜치에 직접 커밋을 했기 때문입니다. 그 이유는 `upload` 브랜치의 내용이 원격과 로컬에서 각각 달라졌기 때문에, git이 원격과 로컬 중 무엇을 유지하고 무엇을 버릴 지 모르기 때문입니다. 이를 고치려면, 새 브랜치를 만들고, `upstream/upload` 브랜치와 분기된 지점을 찾은 다음, `upload` 브랜치를 그 지점으로 되돌려야 합니다. +`git pull --ff-only`를 실행했더니 에러가 났다면, `upload` 브랜치에 직접 커밋을 했기 때문입니다. 그 +이유는 `upload` 브랜치의 내용이 원격과 로컬에서 각각 달라졌기 때문에, git이 원격과 로컬 중 무엇을 +유지하고 무엇을 버릴 지 모르기 때문입니다. 이를 고치려면, 새 브랜치를 만들고, `upstream/upload` +브랜치와 분기된 지점을 찾은 다음, `upload` 브랜치를 그 지점으로 되돌려야 합니다. ```sh $ git pull --ff-only upstream upload @@ -374,7 +438,8 @@ $ git reset --hard cc31d0.... HEAD is now at cc31d0... ... ``` -이제 `upload`가 정리되었으니 `upstream/upload`에서 변경 내역을 끌어오고, `new_branch`에서 계속 작업할 수 있습니다. +이제 `upload`가 정리되었으니 `upstream/upload`에서 변경 내역을 끌어오고, `new_branch`에서 계속 +작업할 수 있습니다. ```sh $ git pull --ff-only upstream upload diff --git a/doc/CONTRIBUTING.md b/doc/CONTRIBUTING.md index 86948f56091f..5cb202d96e08 100644 --- a/doc/CONTRIBUTING.md +++ b/doc/CONTRIBUTING.md @@ -1,7 +1,6 @@ # Contribute -[![en][icon-en]][en] -[![ko][icon-ko]][ko] +[![en][icon-en]][en] [![ko][icon-ko]][ko] [en]: ./CONTRIBUTING.md [icon-en]: https://img.shields.io/badge/lang-en-red?style=flat-square @@ -11,6 +10,9 @@ - [Contribute](#contribute) - [Guidelines](#guidelines) - [Code Style](#code-style) + - [C++](#c) + - [JSON](#json) + - [Markdown](#markdown) - [Translations](#translations) - [Documentation](#documentation) - [Doxygen Comments](#doxygen-comments) @@ -42,27 +44,56 @@ Contributing to Cataclysm: Bright Nights is easy: 1. Make your changes. 1. Send us a pull request. -> Cataclysm: Bright Nights is released under the Creative Commons Attribution ShareAlike 3.0 license. The code and content of the game is free to use, modify, and redistribute for any purpose whatsoever. See http://creativecommons.org/licenses/by-sa/3.0/ for details. -> This means any contribution you make to the project will also be covered by the same license, and this license is irrevocable. +> Cataclysm: Bright Nights is released under the Creative Commons Attribution ShareAlike 3.0 +> license. The code and content of the game is free to use, modify, and redistribute for any purpose +> whatsoever. See http://creativecommons.org/licenses/by-sa/3.0/ for details. This means any +> contribution you make to the project will also be covered by the same license, and this license is +> irrevocable. ## Guidelines There are a couple of guidelines we suggest sticking to: - Add this repository as an `upstream` remote. -- Keep your `upload` branch clean. This means you can easily pull changes made to this repository into yours. +- Keep your `upload` branch clean. This means you can easily pull changes made to this repository + into yours. - Create a new branch for each new feature or set of related bug fixes. -- Never merge from your local branches into your `upload` branch. Only update that by pulling from `upstream/upload`. +- Never merge from your local branches into your `upload` branch. Only update that by pulling from + `upstream/upload`. ## Code Style -Code style is enforced across the codebase by `astyle`. -See [CODE_STYLE](../doc/CODE_STYLE.md) for details. +### C++ + +Code style is enforced across the codebase by `astyle`. See [CODE_STYLE](../doc/CODE_STYLE.md) for +details. + +### JSON + +JSON files are formatted using custom formatter available in `tools/format`. Visit +[JSON Style Guide](../doc/JSON_STYLE.md) for details. + +### Markdown + +Markdown files such as `doc/` are formatted using [`deno`](https://deno.com)'s built-in formatter. +Run [`deno fmt`](https://deno.land/manual/tools/formatter) anywhere to format markdown files. On +VSCode, you can set following configuration to auto-format markdown files on save: + +```json +// .vscode/settings.json +{ + "[markdown]": { + "editor.formatOnSave": true, + "editor.defaultFormatter": "denoland.vscode-deno" + } +} +``` ## Translations -The translation of Cataclysm: BN is done using Transifex. -Look at the [translation project](https://app.transifex.com/bn-team/cataclysm-bright-nights/) for an up-to-date list of supported languages. +The translation of Cataclysm: BN is done using Transifex. Look at the +[translation project](https://app.transifex.com/bn-team/cataclysm-bright-nights/) for an up-to-date +list of supported languages. See [TRANSLATING](../doc/TRANSLATING.md) for more information: @@ -77,11 +108,13 @@ See [TRANSLATING](../doc/TRANSLATING.md) for more information:

-Autogenerated documentation is hosted on [GitHub Pages](https://cataclysmbnteam.github.io/Cataclysm-BN). +Autogenerated documentation is hosted on +[GitHub Pages](https://cataclysmbnteam.github.io/Cataclysm-BN). ### Doxygen Comments -Extensive documentation of classes and class members will make the code more readable to new contributors. New doxygen comments for existing classes are a welcomed contribution. +Extensive documentation of classes and class members will make the code more readable to new +contributors. New doxygen comments for existing classes are a welcomed contribution. Use the following template for commenting classes: @@ -116,7 +149,8 @@ int foo; ### Guidelines for adding documentation -- Doxygen comments should describe behavior towards the outside, not implementation, but since many classes in Cataclysm are intertwined, it's often necessary to describe implementation. +- Doxygen comments should describe behavior towards the outside, not implementation, but since many + classes in Cataclysm are intertwined, it's often necessary to describe implementation. - Describe things that aren't obvious to newcomers just from the name. - Don't describe redundantly: `/** Map **/; map* map;` is not a helpful comment. - When documenting X, describe how X interacts with other components, not just what X itself does. @@ -124,7 +158,7 @@ int foo; ### Building the documentation for viewing it locally - Install doxygen -- `doxygen doxygen_doc/doxygen_conf.txt ` +- `doxygen doxygen_doc/doxygen_conf.txt` - `firefox doxygen_doc/html/index.html` (replace firefox with your browser of choice) ## Example Workflow @@ -145,7 +179,7 @@ $ git clone https://github.com/YOUR_USERNAME/Cataclysm-BN.git 3. Set commit message template. ```sh - $ git config --local commit.template .gitmessage +$ git config --local commit.template .gitmessage ``` 4. Add this repository as a remote. @@ -178,7 +212,9 @@ $ git pull --ff-only upstream upload # gets changes from "upload" branch on the "upstream" remote ``` -> **Note** If this gives you an error, it means you have committed directly to your local `upload` branch. [Click here for instructions on how to fix this issue](#why-does-git-pull---ff-only-result-in-an-error). +> **Note** If this gives you an error, it means you have committed directly to your local `upload` +> branch. +> [Click here for instructions on how to fix this issue](#why-does-git-pull---ff-only-result-in-an-error). ### Make your changes @@ -200,31 +236,42 @@ $ git push origin new_feature # origin was automatically set to point to your fork when you cloned it ``` -3. Once you're finished working on your branch, and have committed and pushed all your changes, submit a pull request from your `new_feature` branch to this repository's `upload` branch. +3. Once you're finished working on your branch, and have committed and pushed all your changes, + submit a pull request from your `new_feature` branch to this repository's `upload` branch. -> **Note** any new commits to the `new_feature` branch on GitHub will automatically be included in the pull request, so make sure to only commit related changes to the same branch. +> **Note** any new commits to the `new_feature` branch on GitHub will automatically be included in +> the pull request, so make sure to only commit related changes to the same branch. ## Pull Request Notes -If you file a PR but you're still working on it, please mark it as [draft](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests). This can help speed up our review process by allowing us to only review the things that are ready for it, and will prevent anything that isn't completely ready from being merged in. +If you file a PR but you're still working on it, please mark it as +[draft](https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests#draft-pull-requests). +This can help speed up our review process by allowing us to only review the things that are ready +for it, and will prevent anything that isn't completely ready from being merged in. -It is not required to solve or reference an open issue to file a PR, however, if you do so, you need to explain the problem your PR is solving in full detail. +It is not required to solve or reference an open issue to file a PR, however, if you do so, you need +to explain the problem your PR is solving in full detail. ### All PRs should have a `"Summary"` line -Summary is a one-line description of your change that will be extracted and added to the project changelog at +Summary is a one-line description of your change that will be extracted and added to the project +changelog at The format is: `SUMMARY: Category "description"` -The categories to choose from are: Features, Content, Interface, Mods, Balance, Bugfixes, Performance, Infrastructure, Build, I18N. +The categories to choose from are: Features, Content, Interface, Mods, Balance, Bugfixes, +Performance, Infrastructure, Build, I18N. Example: `SUMMARY: Content "Adds new mutation category 'Mouse'"` -See the [Changelog Guidelines](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/doc/CHANGELOG_GUIDELINES.md) for explanations of the categories. +See the +[Changelog Guidelines](https://github.com/cataclysmbnteam/Cataclysm-BN/blob/upload/doc/CHANGELOG_GUIDELINES.md) +for explanations of the categories. ### Closing issues using keywords -One more thing: when marking your PR as closing, fixing, or resolving issues, please include this somewhere in the description: +One more thing: when marking your PR as closing, fixing, or resolving issues, please include this +somewhere in the description: ``` - {keyword} #{issue} @@ -244,7 +291,8 @@ for example: `- fixed #12345` and `{issue}` is the number of the issue you're closing after PR gets merged. -This would automatically close the issue when the PR is pulled in, and allows merges to work slightly faster. +This would automatically close the issue when the PR is pulled in, and allows merges to work +slightly faster. ### closing multiple issues at once @@ -256,7 +304,8 @@ See for more. ## Tooling support -Various tools are available to help you keep your contributions conforming to the appropriate style. See [DEVELOPER_TOOLING](../doc/DEVELOPER_TOOLING.md) for more details. +Various tools are available to help you keep your contributions conforming to the appropriate style. +See [DEVELOPER_TOOLING](../doc/DEVELOPER_TOOLING.md) for more details. ## Advanced Techniques @@ -264,7 +313,8 @@ These guidelines aren't essential, but they can make keeping things in order muc ### Using remote tracking branches -Remote tracking branches allow you to easily stay in touch with this repository's `upload` branch, as they automatically know which remote branch to get changes from. +Remote tracking branches allow you to easily stay in touch with this repository's `upload` branch, +as they automatically know which remote branch to get changes from. ```sh $ git branch -vv @@ -272,7 +322,9 @@ $ git branch -vv new_feature xxxx .... ``` -Here you can see we have two branches; `upload` which is tracking `origin/upload`, and `new_feature` which isn't tracking any branch. In practice, what this means is that git won't know where to get changes from. +Here you can see we have two branches; `upload` which is tracking `origin/upload`, and `new_feature` +which isn't tracking any branch. In practice, what this means is that git won't know where to get +changes from. ```sh $ git checkout new_feature @@ -282,7 +334,8 @@ There is no tracking information for the current branch. Please specify which branch you want to merge with. ``` -In order to easily pull changes from `upstream/upload` into the `new_feature` branch, we can tell git which branch it should track. (You can even do this for your local upload branch.) +In order to easily pull changes from `upstream/upload` into the `new_feature` branch, we can tell +git which branch it should track. (You can even do this for your local upload branch.) ```sh $ git branch -u upstream/upload new_feature @@ -299,7 +352,9 @@ $ git branch new_feature_2 --track upstream/upload Branch new_feature_2 set up to track remote branch upload from upstream. ``` -> **Note**: Although this makes it easier to pull from `upstream/upload`, it doesn't change anything with regards to pushing. `git push` fails because you don't have permission to push to `upstream/upload`. +> **Note**: Although this makes it easier to pull from `upstream/upload`, it doesn't change anything +> with regards to pushing. `git push` fails because you don't have permission to push to +> `upstream/upload`. ```sh $ git push @@ -313,11 +368,11 @@ xxxx..xxxx new_feature -> new_feature ## Unit tests -There is a suite of tests built into the source tree at tests/ -You should run the test suite after ANY change to the game source. -An ordinary invocation of `make` will build the test executable at tests/cata_test, and it can be invoked like any ordinary executable, or via `make check`. -With no arguments it will run the entire test suite. -With `--help` it will print a number of invocation options you can use to adjust its operation. +There is a suite of tests built into the source tree at tests/ You should run the test suite after +ANY change to the game source. An ordinary invocation of `make` will build the test executable at +tests/cata_test, and it can be invoked like any ordinary executable, or via `make check`. With no +arguments it will run the entire test suite. With `--help` it will print a number of invocation +options you can use to adjust its operation. ```sh $ make @@ -334,9 +389,16 @@ I recommend habitually invoking make like `make YOUR BUILD OPTIONS && make check ## In-game testing, test environment and the debug menu -Whether you are implementing a new feature or whether you are fixing a bug, it is always a good practice to test your changes in-game. It can be a hard task to create the exact conditions by playing a normal game to be able to test your changes, which is why there is a debug menu. There is no default key to bring up the menu so you will need to assign one first. +Whether you are implementing a new feature or whether you are fixing a bug, it is always a good +practice to test your changes in-game. It can be a hard task to create the exact conditions by +playing a normal game to be able to test your changes, which is why there is a debug menu. There is +no default key to bring up the menu so you will need to assign one first. -Bring up the keybindings menu (press `Escape` then `1`), scroll down almost to the bottom and press `+` to add a new key binding. Press the letter that corresponds to the _Debug menu_ item, then press the key you want to use to bring up the debug menu. To test your changes, create a new world with a new character. Once you are in that world, press the key you just assigned for the debug menu and you should see something like this: +Bring up the keybindings menu (press `Escape` then `1`), scroll down almost to the bottom and press +`+` to add a new key binding. Press the letter that corresponds to the _Debug menu_ item, then press +the key you want to use to bring up the debug menu. To test your changes, create a new world with a +new character. Once you are in that world, press the key you just assigned for the debug menu and +you should see something like this: ``` ┌─────────────────────────────────────────────────────┐ @@ -351,13 +413,17 @@ Bring up the keybindings menu (press `Escape` then `1`), scroll down almost to t └─────────────────────────────────────────────────────┘ ``` -With these commands, you should be able to recreate the proper conditions to test your changes. The [DDA wiki](http://cddawiki.chezzo.com/cdda_wiki/index.php) may have useful informations regarding debug menu. +With these commands, you should be able to recreate the proper conditions to test your changes. The +[DDA wiki](http://cddawiki.chezzo.com/cdda_wiki/index.php) may have useful informations regarding +debug menu. ## Frequently Asked Questions ### Why does `git pull --ff-only` result in an error? -If `git pull --ff-only` shows an error, it means that you've committed directly to your local `upload` branch. To fix this, we create a new branch with these commits, find the point at which we diverged from `upstream/upload`, and then reset `upload` to that point. +If `git pull --ff-only` shows an error, it means that you've committed directly to your local +`upload` branch. To fix this, we create a new branch with these commits, find the point at which we +diverged from `upstream/upload`, and then reset `upload` to that point. ```sh $ git pull --ff-only upstream upload @@ -371,7 +437,8 @@ $ git reset --hard cc31d0.... HEAD is now at cc31d0... ... ``` -Now that `upload` has been cleaned up, we can easily pull from `upstream/upload`, and then continue working on `new_branch`. +Now that `upload` has been cleaned up, we can easily pull from `upstream/upload`, and then continue +working on `new_branch`. ```sh $ git pull --ff-only upstream upload diff --git a/doc/DEVELOPER_FAQ.md b/doc/DEVELOPER_FAQ.md index ca011146ce34..cb2d88693077 100644 --- a/doc/DEVELOPER_FAQ.md +++ b/doc/DEVELOPER_FAQ.md @@ -2,23 +2,40 @@ ## Adding a monster -1. Edit `data/json/monsters.json` or create a new json file and insert the definition of your new monster there (probably copy an existing entry). +1. Edit `data/json/monsters.json` or create a new json file and insert the definition of your new + monster there (probably copy an existing entry). 2. Make sure the id value is unique among all other monster types. -3. Your monster type is now valid, but won't be spawned. If you want it to be spawned among similar monsters, edit monstergroups.json. Find the appropriate array, and insert the identifier for your monster (e.g, `mon_zombie`). `cost_multiplier`, makes it more expensive to spawn. The higher the cost, the more 'slots' it takes up, and freq is how frequent they spawn. See `mongroupdef.cpp` -4. If you want your monster to drop items, edit `monster_drops.json`. Make a new array for your monster type with all the map item groups it may carry, and a chance value for each. -5. Your monster may have a special attack, a `monattack::function` reference. Edit `monattack.h` and include the function in the class definition; edit `monstergenerator.cpp` and add the translation, then edit `monattack.cpp` and define your function. Functions may be shared among different monster types. Be aware that the function should contain a statement that the monster uses to decide whether or not to use the attack, and if they do, should reset the monster's attack timer. -6. Just like attacks, some monsters may have a special function called when they die. This works the same as attacks, but the relevant files are `mondeath.h` and `mondeath.cpp`. -7. If you add flags, document them in `JSON_FLAGS.md`, and `mtype.h`. Please. Or we will replace your blood with acid in the night. +3. Your monster type is now valid, but won't be spawned. If you want it to be spawned among similar + monsters, edit monstergroups.json. Find the appropriate array, and insert the identifier for your + monster (e.g, `mon_zombie`). `cost_multiplier`, makes it more expensive to spawn. The higher the + cost, the more 'slots' it takes up, and freq is how frequent they spawn. See `mongroupdef.cpp` +4. If you want your monster to drop items, edit `monster_drops.json`. Make a new array for your + monster type with all the map item groups it may carry, and a chance value for each. +5. Your monster may have a special attack, a `monattack::function` reference. Edit `monattack.h` and + include the function in the class definition; edit `monstergenerator.cpp` and add the + translation, then edit `monattack.cpp` and define your function. Functions may be shared among + different monster types. Be aware that the function should contain a statement that the monster + uses to decide whether or not to use the attack, and if they do, should reset the monster's + attack timer. +6. Just like attacks, some monsters may have a special function called when they die. This works the + same as attacks, but the relevant files are `mondeath.h` and `mondeath.cpp`. +7. If you add flags, document them in `JSON_FLAGS.md`, and `mtype.h`. Please. Or we will replace + your blood with acid in the night. ## Adding structures to the map -Most "regular" buildings are spawned in cities (large clusters of buildings which are located rather close to each other). +Most "regular" buildings are spawned in cities (large clusters of buildings which are located rather +close to each other). -In file `omdata.h` in the enum `oter_id` structure define names (code identifiers) for your building. +In file `omdata.h` in the enum `oter_id` structure define names (code identifiers) for your +building. -If you want your building to be displayed at overmap in different orientations, you should add 4 identifiers for each orientation (`south`, `east`, `west` and `north` correspondingly). +If you want your building to be displayed at overmap in different orientations, you should add 4 +identifiers for each orientation (`south`, `east`, `west` and `north` correspondingly). -In the same file in structure `const oter_t oterlist[num_ter_types]` we should define how these buildings will be displayed, how much they obscure vision and which extras set they have. For example: +In the same file in structure `const oter_t oterlist[num_ter_types]` we should define how these +buildings will be displayed, how much they obscure vision and which extras set they have. For +example: ```C++ {"mil. surplus", '^', c_white, 5, build_extras, false, false}, @@ -27,37 +44,54 @@ In the same file in structure `const oter_t oterlist[num_ter_types]` we should d {"mil. surplus", '<', c_white, 5, build_extras, false, false} ``` -Comments at the beginning of this structure are rather useful. In the file `mapgen.cpp` find the subroutine called `draw_map(...);` where you should find a huge variant operator ("switch"). This is where you should put your code defining the new building by adding new case-statement. +Comments at the beginning of this structure are rather useful. In the file `mapgen.cpp` find the +subroutine called `draw_map(...);` where you should find a huge variant operator ("switch"). This is +where you should put your code defining the new building by adding new case-statement. It should be mentioned that most buildings are built on the square `SEEX*2 x SEEY*2` tiles. -If you want your building to be spawned not only in city limits you should refer to structures in file `omdata.h` (starting from the line `#define OMSPEC_FREQ 7`). +If you want your building to be spawned not only in city limits you should refer to structures in +file `omdata.h` (starting from the line `#define OMSPEC_FREQ 7`). -These structures are also commented in source code. Add new identifier in enum `omspec_id` structure before `NUM_OMSPECS` and then add a record in `const overmap_special overmap_specials[NUM_OMSPECS]` array. For example: +These structures are also commented in source code. Add new identifier in enum `omspec_id` structure +before `NUM_OMSPECS` and then add a record in `const overmap_special overmap_specials[NUM_OMSPECS]` +array. For example: ```C++ {ot_toxic_dump, 0, 5, 15, -1, mcat_null, 0, 0, 0, 0, &omspec_place::wilderness,0} ``` -The comments given in source code to structure `struct overmap_special` explain the meaning of these constants in the example above. +The comments given in source code to structure `struct overmap_special` explain the meaning of these +constants in the example above. ## Adding a bionic -1. Edit `data/json/bionics.json` and add your bionic near similar types. See `JSON_INFO.md` for a more in-depth review of the individual fields. -2. If you want the bionic to be available in the game world as an item, add it to `item_groups.json`, and add a bionic item to `data/json/items/bionics.json`. -3. Manually code in effects into the appropriate files, for activated bionics edit the `player::activate_bionic` function in `bionics.cpp`. -4. For bionic ranged weapons add the bionic weapon counterparts to `ranged.json`, give them the `BIONIC_WEAPON` flags. -5. For bionic close combat weapons add the bionic weapon to `data/json/items/melee.json` give them `NON_STUCK`, `NO_UNWIELD` at least. +1. Edit `data/json/bionics.json` and add your bionic near similar types. See `JSON_INFO.md` for a + more in-depth review of the individual fields. +2. If you want the bionic to be available in the game world as an item, add it to + `item_groups.json`, and add a bionic item to `data/json/items/bionics.json`. +3. Manually code in effects into the appropriate files, for activated bionics edit the + `player::activate_bionic` function in `bionics.cpp`. +4. For bionic ranged weapons add the bionic weapon counterparts to `ranged.json`, give them the + `BIONIC_WEAPON` flags. +5. For bionic close combat weapons add the bionic weapon to `data/json/items/melee.json` give them + `NON_STUCK`, `NO_UNWIELD` at least. ## How armor protection is calculated -1. When the player is hit at a specific body part, armor coverage determines whether the armor is hit, or an uncovered part of the player is hit (roll `1d100` against coverage). -2. If the above roll fails (ie roll value is above coverage), then the armor does not absorb any damage from the blow, neither does it become damaged. -3. If the above roll succeeds, the armor is hit, possibly absorbing some damage and possibly getting damaged in the process. +1. When the player is hit at a specific body part, armor coverage determines whether the armor is + hit, or an uncovered part of the player is hit (roll `1d100` against coverage). +2. If the above roll fails (ie roll value is above coverage), then the armor does not absorb any + damage from the blow, neither does it become damaged. +3. If the above roll succeeds, the armor is hit, possibly absorbing some damage and possibly getting + damaged in the process. 4. The above steps are repeated for each layer of armor on the body part. -5. Armor protects against bash and cut damage. These are determined by multiplying the armor thickness by the material bash/cut resistance factor respectively, given in `materials.json`. -6. If the armor is made from 2 materials types, then it takes a weighted average of the primary material (`66%`) and secondary material (`33%`). -7. Materials resistance factors are given relative to `PAPER` as a material (this probably needs some fine-tuning for balance). +5. Armor protects against bash and cut damage. These are determined by multiplying the armor + thickness by the material bash/cut resistance factor respectively, given in `materials.json`. +6. If the armor is made from 2 materials types, then it takes a weighted average of the primary + material (`66%`) and secondary material (`33%`). +7. Materials resistance factors are given relative to `PAPER` as a material (this probably needs + some fine-tuning for balance). ## Adding an iuse function. @@ -67,7 +101,8 @@ The comments given in source code to structure `struct overmap_special` explain ## Acid resistance -This determines how items react to acid fields. Item acid resistances are a weighted average of the materials acid resistance (see `item::acid_resist`): +This determines how items react to acid fields. Item acid resistances are a weighted average of the +materials acid resistance (see `item::acid_resist`): - An item acid resistance of zero means it will get corroded every turn; - An item acid resistance above zero means it has a chance of getting corroded every turn; @@ -88,8 +123,22 @@ A: Add the `TRADER_AVOID` flag to it. **Q: What the heck is up with the map objects?** -A: The pertinent map objects are submap, mapbuffer, map, and overmap. The submap contains the actual map data, in SEEXxSEEY chunks. Vehicles and spawns are stored in vectors because they are relatively sparse. Submaps live in the single global mapbuffer, MAPBUFFER. Map encapsulates the area around the player that is currently active. It contains an array of MAPSIZE * MAPSIZE submap pointers called grid. This is a 2D array, but is mapped to a 1D array for (questionable) indexing purposes. When the player moves from one submap to another, `map::shift()` is called. It moves the pointers in grid to keep the player centered. The leading edge of grid is populated by `map::load()`. If the submap has been visited before, it's loaded from MAPBUFFER. Otherwise a 2x2 chunk of submaps is generated based on the corresponding overmap square type. An overmap encapsulates the large-scale structure of a map (such as location and layout of cities, forests, rivers, roads, etc...). There are an arbitrary number of overmaps. Additional overmaps are generated as the player enters new areas. - -**Q: What is the relation of NPCs/Monsters vs maps. How are they stored, where are they stored? Are they stored?** - -A: All npcs are now stored in the overmap. Active npcs only contain the currently active npcs. There is a difference between npc active npc coordinates, and overmap coordinates. So these will need to be changed when saving the npcs. Or else the npcs will be saved at the wrong location. And yes they are stored. +A: The pertinent map objects are submap, mapbuffer, map, and overmap. The submap contains the actual +map data, in SEEXxSEEY chunks. Vehicles and spawns are stored in vectors because they are relatively +sparse. Submaps live in the single global mapbuffer, MAPBUFFER. Map encapsulates the area around the +player that is currently active. It contains an array of MAPSIZE * MAPSIZE submap pointers called +grid. This is a 2D array, but is mapped to a 1D array for (questionable) indexing purposes. When the +player moves from one submap to another, `map::shift()` is called. It moves the pointers in grid to +keep the player centered. The leading edge of grid is populated by `map::load()`. If the submap has +been visited before, it's loaded from MAPBUFFER. Otherwise a 2x2 chunk of submaps is generated based +on the corresponding overmap square type. An overmap encapsulates the large-scale structure of a map +(such as location and layout of cities, forests, rivers, roads, etc...). There are an arbitrary +number of overmaps. Additional overmaps are generated as the player enters new areas. + +**Q: What is the relation of NPCs/Monsters vs maps. How are they stored, where are they stored? Are +they stored?** + +A: All npcs are now stored in the overmap. Active npcs only contain the currently active npcs. There +is a difference between npc active npc coordinates, and overmap coordinates. So these will need to +be changed when saving the npcs. Or else the npcs will be saved at the wrong location. And yes they +are stored. diff --git a/doc/DEVELOPER_TOOLING.md b/doc/DEVELOPER_TOOLING.md index 05dc810f8d3e..afd3da703686 100644 --- a/doc/DEVELOPER_TOOLING.md +++ b/doc/DEVELOPER_TOOLING.md @@ -1,8 +1,10 @@ ## Code style (astyle) -Automatic formatting of the source code is performed by [Artistic Style](http://astyle.sourceforge.net/), or `astyle` for short. +Automatic formatting of the source code is performed by +[Artistic Style](http://astyle.sourceforge.net/), or `astyle` for short. -There are multiple ways to invoke it on the codebase, depending on your system or personal preferences. +There are multiple ways to invoke it on the codebase, depending on your system or personal +preferences. ### Invoking astyle directly @@ -22,9 +24,9 @@ make astyle ### Invoking astyle via pre-commit hook -If you have all the relevant tools installed, you can have git automatically -check the style of code and json by adding these commands to your git -pre-commit hook (typically at `.git/hooks/pre-commit`): +If you have all the relevant tools installed, you can have git automatically check the style of code +and json by adding these commands to your git pre-commit hook (typically at +`.git/hooks/pre-commit`): ```BASH git diff --cached --name-only -z HEAD | grep -z 'data/.*\.json' | \ @@ -35,33 +37,49 @@ make astyle-check || exit 1 ### Astyle extensions for Visual Studio -There are astyle extensions in the Visual Studio Marketplace, but none of them have been confirmed (yet) to correctly work for our purposes on VS2019 or VS2022. +There are astyle extensions in the Visual Studio Marketplace, but none of them have been confirmed +(yet) to correctly work for our purposes on VS2019 or VS2022. #### Visual Studio 2022 -Head over to https://github.com/olanti-p/BN_Astyle and follow instructions in the [README.md](https://github.com/olanti-p/BN_Astyle/blob/master/README.md). You may compile and install the extension from source, or take advantage of the pre-built version in [releases section](https://github.com/olanti-p/BN_Astyle/releases). +Head over to https://github.com/olanti-p/BN_Astyle and follow instructions in the +[README.md](https://github.com/olanti-p/BN_Astyle/blob/master/README.md). You may compile and +install the extension from source, or take advantage of the pre-built version in +[releases section](https://github.com/olanti-p/BN_Astyle/releases). #### Visual Studio 2019 -Extensions's source code lives over at https://github.com/lukamicoder/astyle-extension. -To install and compile it: -1. Add the `Visual Studio extension development` workload through Visual Studio installer to your VS2019 -2. Download and extract the source code, or clone the repository (a simple `git clone --depth 1 https://github.com/lukamicoder/astyle-extension.git` should do). +Extensions's source code lives over at https://github.com/lukamicoder/astyle-extension. To install +and compile it: + +1. Add the `Visual Studio extension development` workload through Visual Studio installer to your + VS2019 +2. Download and extract the source code, or clone the repository (a simple + `git clone --depth 1 https://github.com/lukamicoder/astyle-extension.git` should do). 3. From the root folder, open `astyle-extension/AStyleExtension2017.sln` -4. Select `Release` build configuration (most likely VS will select `Debug` configuration by default) +4. Select `Release` build configuration (most likely VS will select `Debug` configuration by + default) 5. Build the solution -6. If the build succeeded, you'll see the compiled extension in `AStyleExtension\bin\Release`. Double click it to install. -7. Configure the extension according to [Configuration instructions (Visual Studio 2019 or older)](#configuration-instructions-visual-studio-2019-or-older) section. +6. If the build succeeded, you'll see the compiled extension in `AStyleExtension\bin\Release`. + Double click it to install. +7. Configure the extension according to + [Configuration instructions (Visual Studio 2019 or older)](#configuration-instructions-visual-studio-2019-or-older) + section. #### Visual Studio 2017 or earlier -You may follow the steps for VS2019 to compile from source, but there are pre-built versions [available](https://marketplace.visualstudio.com/items?itemName=Lukamicoder.AStyleExtension2017) on Visual Studio Marketplace, you should be able to install the extension through VS's extension manager and then configure it the same way. +You may follow the steps for VS2019 to compile from source, but there are pre-built versions +[available](https://marketplace.visualstudio.com/items?itemName=Lukamicoder.AStyleExtension2017) on +Visual Studio Marketplace, you should be able to install the extension through VS's extension +manager and then configure it the same way. #### Configuration instructions (Visual Studio 2019 or older): 1. Go to `Tools` - `Options` - `AStyle Formatter` - `General`. -2. Import `https://github.com/CleverRaven/Cataclysm-DDA/blob/master/msvc-full-features/AStyleExtension-Cataclysm-DDA.cfg` on `Export/Import` tab using `Import` button: +2. Import + `https://github.com/CleverRaven/Cataclysm-DDA/blob/master/msvc-full-features/AStyleExtension-Cataclysm-DDA.cfg` + on `Export/Import` tab using `Import` button: ![image](img/VS_Astyle_Step_1.png) @@ -69,11 +87,13 @@ You may follow the steps for VS2019 to compile from source, but there are pre-bu ![image](img/VS_Astyle_Step_2.png) -4. Close `Options` menu, open file to be astyled and use `Format Document (Astyle)` or `Format Selection (Astyle)` commands from `Edit` - `Advanced` menu. +4. Close `Options` menu, open file to be astyled and use `Format Document (Astyle)` or + `Format Selection (Astyle)` commands from `Edit` - `Advanced` menu. ![image](img/VS_Astyle_Step_3.png) -*Note:* You can also configure keybindings for aforementioned commands in `Tools` - `Options` - `Environment` - `Keybindings` menu: +_Note:_ You can also configure keybindings for aforementioned commands in `Tools` - `Options` - +`Environment` - `Keybindings` menu: ![image](img/VS_Astyle_Step_4.png) @@ -83,78 +103,81 @@ See the [JSON style guide](JSON_STYLE.md). ## ctags -In addition to the usual means of creating a `tags` file via e.g. [`ctags`](http://ctags.sourceforge.net/), we provide `tools/json_tools/cddatags.py` to augment a `tags` file with locations of definitions taken from CDDA JSON data. `cddatags.py` is designed to safely update a tags file containing source code tags, so if you want both types of tag in your `tags` file then you can run `ctags -R . && tools/json_tools/cddatags.py`. Alternatively, there is a rule in the `Makefile` to do this for you; just run `make ctags` or `make etags`. - +In addition to the usual means of creating a `tags` file via e.g. +[`ctags`](http://ctags.sourceforge.net/), we provide `tools/json_tools/cddatags.py` to augment a +`tags` file with locations of definitions taken from CDDA JSON data. `cddatags.py` is designed to +safely update a tags file containing source code tags, so if you want both types of tag in your +`tags` file then you can run `ctags -R . && tools/json_tools/cddatags.py`. Alternatively, there is a +rule in the `Makefile` to do this for you; just run `make ctags` or `make etags`. ## clang-tidy -Cataclysm has a [clang-tidy configuration file](../.clang-tidy) and if you have -`clang-tidy` available you can run it to perform static analysis of the -codebase. We test with `clang-tidy` from LLVM 12.0.0 with CI, so for the most -consistent results, you might want to use that version. +Cataclysm has a [clang-tidy configuration file](../.clang-tidy) and if you have `clang-tidy` +available you can run it to perform static analysis of the codebase. We test with `clang-tidy` from +LLVM 12.0.0 with CI, so for the most consistent results, you might want to use that version. To run it, you have a few options. -* `clang-tidy` ships with a wrapper script `run-clang-tidy.py`. +- `clang-tidy` ships with a wrapper script `run-clang-tidy.py`. -* Use CMake's built-in support by adding `-DCMAKE_CXX_CLANG_TIDY=clang-tidy` - or similar, pointing it to your chosen clang-tidy version. +- Use CMake's built-in support by adding `-DCMAKE_CXX_CLANG_TIDY=clang-tidy` or similar, pointing it + to your chosen clang-tidy version. + +- To run `clang-tidy` directly try something like -* To run `clang-tidy` directly try something like ```sh grep '"file": "' build/compile_commands.json | \ sed "s+.*$PWD/++;s+\"$++" | \ egrep '.' | \ xargs -P 9 -n 1 clang-tidy -quiet ``` -To focus on a subset of files add their names into the `egrep` regex in the -middle of the command-line. + +To focus on a subset of files add their names into the `egrep` regex in the middle of the +command-line. ### Custom clang-tidy plugin -We have written our own clang-tidy checks in a custom plugin. Unfortunately, -`clang-tidy` as distributed by LLVM doesn't support plugins, so making this -work requires some extra steps. +We have written our own clang-tidy checks in a custom plugin. Unfortunately, `clang-tidy` as +distributed by LLVM doesn't support plugins, so making this work requires some extra steps. #### Ubuntu Focal -If you are on Ubuntu Focal then you might be able to get it working the same -way our CI does. Add the LLVM 12 Focal source [listed -here](https://apt.llvm.org/) to your `sources.list`, install the needed packages (`clang-12 -libclang-12-dev llvm-12-dev llvm-12-tools`), and build Cataclysm with CMake, -adding `-DCATA_CLANG_TIDY_PLUGIN=ON`. +If you are on Ubuntu Focal then you might be able to get it working the same way our CI does. Add +the LLVM 12 Focal source [listed here](https://apt.llvm.org/) to your `sources.list`, install the +needed packages (`clang-12 libclang-12-dev llvm-12-dev llvm-12-tools`), and build Cataclysm with +CMake, adding `-DCATA_CLANG_TIDY_PLUGIN=ON`. On other distributions you will probably need to build `clang-tidy` yourself. -* Check out the `llvm`, `clang`, and `clang-tools-extra` repositories in the - required layout (as described for example + +- Check out the `llvm`, `clang`, and `clang-tools-extra` repositories in the required layout (as + described for example [here](https://quuxplusone.github.io/blog/2018/04/16/building-llvm-from-source/). -* Patch in plugin support for `clang-tidy` using [this - patch](https://github.com/jbytheway/clang-tidy-plugin-support/blob/master/plugin-support.patch). -* Configure LLVM using CMake, including the - `-DCMAKE_EXE_LINKER_FLAGS="-rdynamic"` option. -* Add the `build/bin` directory to your path so that `clang-tidy` and - `FileCheck` are found from there. - -Then you can use your locally build `clang-tidy` to compile Cataclysm. You'll -need to use the CMake version of the Cataclysm build rather than the `Makefile` -build. Add the following CMake options: +- Patch in plugin support for `clang-tidy` using + [this patch](https://github.com/jbytheway/clang-tidy-plugin-support/blob/master/plugin-support.patch). +- Configure LLVM using CMake, including the `-DCMAKE_EXE_LINKER_FLAGS="-rdynamic"` option. +- Add the `build/bin` directory to your path so that `clang-tidy` and `FileCheck` are found from + there. + +Then you can use your locally build `clang-tidy` to compile Cataclysm. You'll need to use the CMake +version of the Cataclysm build rather than the `Makefile` build. Add the following CMake options: + ```sh -DCATA_CLANG_TIDY_PLUGIN=ON -DCATA_CLANG_TIDY_INCLUDE_DIR="$extra_dir/clang-tidy" -DCATA_CHECK_CLANG_TIDY="$extra_dir/test/clang-tidy/check_clang_tidy.py" ``` + where `$extra_dir` is the location of your `clang-tools-extra` checkout. To run `clang-tidy` with this plugin enabled add the -`'-plugins=$build_dir/tools/clang-tidy-plugin/libCataAnalyzerPlugin.so'` option -to your `clang-tidy` command line. +`'-plugins=$build_dir/tools/clang-tidy-plugin/libCataAnalyzerPlugin.so'` option to your `clang-tidy` +command line. -If you wish to run the tests for the custom clang-tidy plugin you will also -need `lit`. This will be built as part of LLVM, or you can install it via -`pip` or your local package manager if you prefer. +If you wish to run the tests for the custom clang-tidy plugin you will also need `lit`. This will be +built as part of LLVM, or you can install it via `pip` or your local package manager if you prefer. + +Then, assuming `build` is your Cataclysm build directory, you can run the tests with -Then, assuming `build` is your Cataclysm build directory, you can run the tests -with ```sh lit -v build/tools/clang-tidy-plugin/test ``` @@ -164,32 +187,33 @@ lit -v build/tools/clang-tidy-plugin/test ##### Build LLVM To build LLVM on Windows, you'll first need to get some tools installed. + - Cmake - Python 3 -- MinGW-w64 (other compilers may or may not work. Clang itself does not seem to be -building LLVM on Windows correctly.) +- MinGW-w64 (other compilers may or may not work. Clang itself does not seem to be building LLVM on + Windows correctly.) - A shell environment -After the tools are installed, a patch still needs to be applied before building -LLVM, since `clang-tidy` as distributed by LLVM doesn't support plugins. +After the tools are installed, a patch still needs to be applied before building LLVM, since +`clang-tidy` as distributed by LLVM doesn't support plugins. -First, clone the LLVM repo from, for example, [the official github repo](https://github.com/llvm/llvm-project.git). -Checkout the `release/12.x` branch, since that's what our patch was based on. +First, clone the LLVM repo from, for example, +[the official github repo](https://github.com/llvm/llvm-project.git). Checkout the `release/12.x` +branch, since that's what our patch was based on. On Windows, in addition to applying `plugin-support.patch` mentioned in the previous section, you should also apply [`clang-tidy-scripts.patch`](https://github.com/jbytheway/clang-tidy-plugin-support/blob/master/clang-tidy-scripts.patch) -so you can run the lit test with the custom clang-tidy executable and let -clang-tidy apply suggestions automatically. +so you can run the lit test with the custom clang-tidy executable and let clang-tidy apply +suggestions automatically. -After the patch is applied, you can then build the LLVM code. Unfortunately, it -seems that clang itself cannot correctly compile the LLVM code on Windows (gives -some sort of relocation error). Luckily, MinGW-w64 can be used instead to compile -the code. +After the patch is applied, you can then build the LLVM code. Unfortunately, it seems that clang +itself cannot correctly compile the LLVM code on Windows (gives some sort of relocation error). +Luckily, MinGW-w64 can be used instead to compile the code. -The first step to build the code is to run CMake to generate the makefile. On -the root dir of LLVM, run the following script (substitute values inside `<>` -with the actual paths). Make sure CMake, python, and MinGW-w64 are on the path. +The first step to build the code is to run CMake to generate the makefile. On the root dir of LLVM, +run the following script (substitute values inside `<>` with the actual paths). Make sure CMake, +python, and MinGW-w64 are on the path. ```sh mkdir -p build @@ -204,10 +228,10 @@ cmake \ ../llvm ``` -The next step is to call `make` to actually build clang-tidy as a library. -When using MinGW-w64 to build, you should call `mingw32-make` instead. -Also, because `FileCheck` is not shipped with Windows, you'll also need to build -it yourself using LLVM sources by adding the `FileCheck` target to the make command. +The next step is to call `make` to actually build clang-tidy as a library. When using MinGW-w64 to +build, you should call `mingw32-make` instead. Also, because `FileCheck` is not shipped with +Windows, you'll also need to build it yourself using LLVM sources by adding the `FileCheck` target +to the make command. ```sh mkdir -p build @@ -215,31 +239,33 @@ cd build mingw32-make -j4 clang-tidy clangTidyMain FileCheck ``` -Here `clang-tidy` is only added to trigger the building of several targets that -are needed to build our custom clang-tidy executable later. +Here `clang-tidy` is only added to trigger the building of several targets that are needed to build +our custom clang-tidy executable later. ##### Build clang-tidy with custom checks -After building clang-tidy as a library from the LLVM source, the next step is to -build clang-tidy as an executable, with the custom checks from the CDDA source. +After building clang-tidy as a library from the LLVM source, the next step is to build clang-tidy as +an executable, with the custom checks from the CDDA source. In this step, the following tools are required. + - Python 3 - CMake - MinGW-w64 - FileCheck (built from the LLVM source) - A shell environment -You also need to install yaml for python 3 to work. Download the `.whl` installer -corresponding to your python version from [here](https://pyyaml.org/wiki/PyYAML) -and execute the following command inside the `/Scripts` directory +You also need to install yaml for python 3 to work. Download the `.whl` installer corresponding to +your python version from [here](https://pyyaml.org/wiki/PyYAML) and execute the following command +inside the `/Scripts` directory + ```sh pip install path/to/your/downloaded/file.whl ``` -Currently, the CDDA source is still building the custom checks as a plugin, -which unfortunately is not supported on Windows, so the following patch needs to -be applied before the custom checks can be built as an executable. +Currently, the CDDA source is still building the custom checks as a plugin, which unfortunately is +not supported on Windows, so the following patch needs to be applied before the custom checks can be +built as an executable. ```patch diff --git a/tools/clang-tidy-plugin/CMakeLists.txt b/tools/clang-tidy-plugin/CMakeLists.txt @@ -309,18 +335,17 @@ index 496804316a..43beb49653 100644 config.substitutions.append(('%cata_plugin', cata_plugin)) ``` -The next step is to run CMake to generate the compilation database. The compilation -database contains compiler flags that clang-tidy uses to check the source files. +The next step is to run CMake to generate the compilation database. The compilation database +contains compiler flags that clang-tidy uses to check the source files. -Make sure Python 3, CMake, MinGW-w64, and FileCheck are on the path. -Note that two `bin` directories of MinGW-w64 should be on the path: `/bin`, -and `/x86_64-w64-mingw32/bin`. FileCheck's path is `/build/bin`, -if you built it with the instructions in the previous section. +Make sure Python 3, CMake, MinGW-w64, and FileCheck are on the path. Note that two `bin` directories +of MinGW-w64 should be on the path: `/bin`, and +`/x86_64-w64-mingw32/bin`. FileCheck's path is `/build/bin`, if +you built it with the instructions in the previous section. -Then add the following CMake options to generate the compilation database -(substitute values inside `<>` with the actual paths), and build the CDDA source -and the custom clang-tidy executable with `mingw32-make`. In this tutorial we -run CMake and `mingw32-make` in the `build` subdirectory. +Then add the following CMake options to generate the compilation database (substitute values inside +`<>` with the actual paths), and build the CDDA source and the custom clang-tidy executable with +`mingw32-make`. In this tutorial we run CMake and `mingw32-make` in the `build` subdirectory. ```sh -DCMAKE_EXPORT_COMPILE_COMMANDS=ON @@ -333,22 +358,20 @@ run CMake and `mingw32-make` in the `build` subdirectory. -DCATA_CHECK_CLANG_TIDY="/clang-tools-extra/test/clang-tidy/check_clang_tidy.py -clang-tidy=/build/tools/clang-tidy-plugin/CataAnalyzerPlugin.exe" ``` -Next, change the directory back to the source root, and run `tools/fix-compilation-database.py` -with Python 3 to fix some errors in the compilation database. Then the compilation -database should be usable by clang-tidy. +Next, change the directory back to the source root, and run `tools/fix-compilation-database.py` with +Python 3 to fix some errors in the compilation database. Then the compilation database should be +usable by clang-tidy. -If you want to check if the custom checks are working correctly, run the following -script. +If you want to check if the custom checks are working correctly, run the following script. ```sh python3 /llvm/utils/lit/lit.py -v build/tools/clang-tidy-plugin/test ``` -Finally, use the following command to run clang-tidy with the custom checks. -In the following command, the first line of "-extra-arg"s are used to tell -clang-tidy to mimic g++ behavior, and the second line of "-extra-arg"s are -used to tell clang-tidy to use clang's x86intrin.h instead of g++'s, so as -to avoid compiler errors. +Finally, use the following command to run clang-tidy with the custom checks. In the following +command, the first line of "-extra-arg"s are used to tell clang-tidy to mimic g++ behavior, and the +second line of "-extra-arg"s are used to tell clang-tidy to use clang's x86intrin.h instead of +g++'s, so as to avoid compiler errors. ```sh python3 /clang-tools-extra/clang-tidy/tool/run-clang-tidy.py \ @@ -358,24 +381,24 @@ python3 /clang-tools-extra/clang-tidy/tool/run-clang-tidy.py \ -extra-arg=-isystem -extra-arg=/clang/lib/Headers ``` -You can also add `-fix-errors` to apply fixes reported by the checks, or -`-checks="-*,xxx,yyy"` to specify the checks you would like to run. +You can also add `-fix-errors` to apply fixes reported by the checks, or `-checks="-*,xxx,yyy"` to +specify the checks you would like to run. ## include-what-you-use -[include-what-you-use](https://github.com/include-what-you-use/include-what-you-use) -(IWYU) is a project intended to optimise includes. It will calculate the -required headers and add and remove includes as appropriate. +[include-what-you-use](https://github.com/include-what-you-use/include-what-you-use) (IWYU) is a +project intended to optimise includes. It will calculate the required headers and add and remove +includes as appropriate. -Running on this codebase revealed some issues. You will need a version of IWYU -where the following PR has been merged (which has not yet happened at time of -writing, but with luck might make it into the clang-10 release of IWYU): +Running on this codebase revealed some issues. You will need a version of IWYU where the following +PR has been merged (which has not yet happened at time of writing, but with luck might make it into +the clang-10 release of IWYU): -* https://github.com/include-what-you-use/include-what-you-use/pull/775 +- https://github.com/include-what-you-use/include-what-you-use/pull/775 -Once you have IWYU built, build the codebase using cmake, with -`CMAKE_EXPORT_COMPILE_COMMANDS=ON` on to create a compilation database -(Look for `compile_commands.json` in the build dir to see whether that worked). +Once you have IWYU built, build the codebase using cmake, with `CMAKE_EXPORT_COMPILE_COMMANDS=ON` on +to create a compilation database (Look for `compile_commands.json` in the build dir to see whether +that worked). Then run: @@ -383,46 +406,40 @@ Then run: iwyu_tool.py -p $CMAKE_BUILD_DIR/compile_commands.json -- -Xiwyu --mapping_file=$PWD/tools/iwyu/cata.imp | fix_includes.py --nosafe_headers --reorder ``` -IWYU will sometimes add C-style library headers which clang-tidy doesn't like, -so you might need to run clang-tidy (as described above) and then re-run IWYU a -second time. - -There are mapping files in `tools/iwyu` intended to help IWYU pick the right -headers. Mostly they should be fairly obvious, but the SDL mappings might -warrant further explanation. We want to force most SDL includes to go via -`sdl_wrappers.h`, because that handles the platform-dependence issues (the -include paths are different on Windows). There are a couple of exceptions -(`SDL_version.h` and `SDL_mixer.h`). The former is because `main.cpp` can't -include all SDL headers, because they `#define WinMain`. All the mappings in -`sdl.imp` are designed to make this happen. - -We have to use IWYU pragmas in some situations. Some of the reasons are: - -* IWYU has a concept of [associated - headers](https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md#iwyu-pragma-associated), - where each cpp file can have some number of such headers. The cpp file is - expected to define the things declared in those headers. In Cata, the - mapping between headers and cpp files is not nearly so simple, so there are - files with multiple associated headers, and files with none. Headers that - are not the associated header of any cpp file will not get their includes - updated, which could lead to broken builds, so ideally all headers would be - associated to some cpp file. You can use the following command to get a list - of headers which are not currently associated to any cpp file (requires GNU - sed): +IWYU will sometimes add C-style library headers which clang-tidy doesn't like, so you might need to +run clang-tidy (as described above) and then re-run IWYU a second time. + +There are mapping files in `tools/iwyu` intended to help IWYU pick the right headers. Mostly they +should be fairly obvious, but the SDL mappings might warrant further explanation. We want to force +most SDL includes to go via `sdl_wrappers.h`, because that handles the platform-dependence issues +(the include paths are different on Windows). There are a couple of exceptions (`SDL_version.h` and +`SDL_mixer.h`). The former is because `main.cpp` can't include all SDL headers, because they +`#define WinMain`. All the mappings in `sdl.imp` are designed to make this happen. + +We have to use IWYU pragmas in some situations. Some of the reasons are: + +- IWYU has a concept of + [associated headers](https://github.com/include-what-you-use/include-what-you-use/blob/master/docs/IWYUPragmas.md#iwyu-pragma-associated), + where each cpp file can have some number of such headers. The cpp file is expected to define the + things declared in those headers. In Cata, the mapping between headers and cpp files is not nearly + so simple, so there are files with multiple associated headers, and files with none. Headers that + are not the associated header of any cpp file will not get their includes updated, which could + lead to broken builds, so ideally all headers would be associated to some cpp file. You can use + the following command to get a list of headers which are not currently associated to any cpp file + (requires GNU sed): ``` diff <(ls src/*.h | sed 's!.*/!!') <(for i in src/*.cpp; do echo $i; sed -n '/^#include/{p; :loop n; p; /^$/q; b loop}' $i; done | grep 'e "' | grep -o '"[^"]*"' | sort -u | tr -d '"') ``` -* Due to a [clang bug](https://bugs.llvm.org/show_bug.cgi?id=20666), uses in - template arguments to explicit instantiations are not counted, which leads to - some need for `IWYU pragma: keep`. +- Due to a [clang bug](https://bugs.llvm.org/show_bug.cgi?id=20666), uses in template arguments to + explicit instantiations are not counted, which leads to some need for `IWYU pragma: keep`. -* Due to +- Due to [these](https://github.com/include-what-you-use/include-what-you-use/blob/4909f206b46809775e9b5381f852eda62cbf4bf7/iwyu.cc#L1617) [missing](https://github.com/include-what-you-use/include-what-you-use/blob/4909f206b46809775e9b5381f852eda62cbf4bf7/iwyu.cc#L1629) - features of IWYU, it does not count uses in template arguments to return - types, which leads to other requirements for `IWYU pragma: keep`. + features of IWYU, it does not count uses in template arguments to return types, which leads to + other requirements for `IWYU pragma: keep`. -* IWYU seems to have particular trouble with types used in maps. Have not looked into this in detail, but again worked - around it with pragmas. +- IWYU seems to have particular trouble with types used in maps. Have not looked into this in + detail, but again worked around it with pragmas. diff --git a/doc/EFFECTS_JSON.md b/doc/EFFECTS_JSON.md index 5ac83156ad3a..0d7d3e2e3416 100644 --- a/doc/EFFECTS_JSON.md +++ b/doc/EFFECTS_JSON.md @@ -1,31 +1,39 @@ # Effect data ## How to give effects in-game? + ### Comestibles -The first way to give a player an effect in-game is through the drug system. To do this your item must have a use_action of type "consume_drug". -```C++ - "use_action" : { - "type" : "consume_drug", - "activation_message" : "You take some oxycodone.", - "effects" : [ - { - "id": "pkill3", - "duration": 20 - }, - { - "id": "pkill2", - "duration": 200 - } - ] - }, + +The first way to give a player an effect in-game is through the drug system. To do this your item +must have a use_action of type "consume_drug". + +```C++ +"use_action" : { + "type" : "consume_drug", + "activation_message" : "You take some oxycodone.", + "effects" : [ + { + "id": "pkill3", + "duration": 20 + }, + { + "id": "pkill2", + "duration": 200 + } + ] +}, ``` + Notice the "effects" field. Each effect has four potential fields: + ```C++ "id" - Required "duration" - Required "bp" - This will cause the effect to target this body part specifically ``` + Valid "bp" entries are (no entry means the effect is untargeted): + ```C++ "torso" "head" @@ -42,120 +50,145 @@ Valid "bp" entries are (no entry means the effect is untargeted): ``` ### Creature attacks -Creatures have an effect field similar to the "consume_drug" entry for items. You can make a creature's attacks apply effects by adding an "attack_effs" entry for the creature. + +Creatures have an effect field similar to the "consume_drug" entry for items. You can make a +creature's attacks apply effects by adding an "attack_effs" entry for the creature. + ```C++ - "attack_effs": [ - { - "//": "applying this multiple times makes intensity go up by 3 instead of 1", - "id": "paralyzepoison", - "duration": 33 - }, - { - "id": "paralyzepoison", - "duration": 33 - }, - { - "id": "paralyzepoison", - "duration": 33 - } - ], +"attack_effs": [ + { + "//": "applying this multiple times makes intensity go up by 3 instead of 1", + "id": "paralyzepoison", + "duration": 33 + }, + { + "id": "paralyzepoison", + "duration": 33 + }, + { + "id": "paralyzepoison", + "duration": 33 + } +], ``` -The fields for "attack_effs" function identically to the ones for "consume_drug". However, creatures have an additional field: + +The fields for "attack_effs" function identically to the ones for "consume_drug". However, creatures +have an additional field: + ```C++ "chance" - The percentage chance of the effect being applied on a good hit, defaults to 100% ``` -If a creature successfully damages the player and their chance roll succeeds they will apply -all of the listed effects to the player. The effects are added one after another. + +If a creature successfully damages the player and their chance roll succeeds they will apply all of +the listed effects to the player. The effects are added one after another. ## Required fields + ```C++ - "type": "effect_type", - Required - "id": "xxxx" - Must be unique +"type": "effect_type", - Required +"id": "xxxx" - Must be unique ``` ## Optional fields ### Max intensity + ```C++ - "max_intensity": 3 - Used for many later fields, defaults to 1 - "max_effective_intensity" - How many intensity levels will apply effects. - Other intensity levels will only increase duration. +"max_intensity": 3 - Used for many later fields, defaults to 1 +"max_effective_intensity" - How many intensity levels will apply effects. + Other intensity levels will only increase duration. ``` ### Name + ```C++ - "name": ["XYZ"] - or - "name": [ - "ABC", - "XYZ", - "123" - ] +"name": ["XYZ"] +or +"name": [ + "ABC", + "XYZ", + "123" +] ``` -If "max_intensity" > 1 and the number of entries in "name" >= "max_intensity" then -it will attempt to use the proper intensity name. In this case that means an intensity -of 1 would give the name "ABC", 2 would give "XYZ", and 3 would give "123". If "max_intensity" == 1 -or the number of entries in "name" is less than "max_intensity", it will use the first entry followed by -the intensity in brackets if the current intensity > 1, i.e. "ABC", "ABC [2]", "ABC [3]". If the desired -entry of "name" is the empty string ("") or "name" is missing then the effect will not display to the player + +If "max_intensity" > 1 and the number of entries in "name" >= "max_intensity" then it will attempt +to use the proper intensity name. In this case that means an intensity of 1 would give the name +"ABC", 2 would give "XYZ", and 3 would give "123". If "max_intensity" == 1 or the number of entries +in "name" is less than "max_intensity", it will use the first entry followed by the intensity in +brackets if the current intensity > 1, i.e. "ABC", "ABC [2]", "ABC [3]". If the desired entry of +"name" is the empty string ("") or "name" is missing then the effect will not display to the player in the status screen. Each entry in "name" can also have an optional context: + ```JSON - "name": [ { "ctxt": "ECIG", "str": "Smoke" } ] +"name": [ { "ctxt": "ECIG", "str": "Smoke" } ] ``` -In this case, the game will translate the name with the given context "ECIG", -which makes it possible to distinguish the verb "Smoke" from the noun "Smoke" -in other languages. + +In this case, the game will translate the name with the given context "ECIG", which makes it +possible to distinguish the verb "Smoke" from the noun "Smoke" in other languages. ```C++ - "speed_name" : "XYZ" - Defaults to the first name value +"speed_name" : "XYZ" - Defaults to the first name value ``` -This is the value used in the list of modifiers on a player's speed. It will default to the first entry in "name" -if it doesn't exist, and if neither one exists or if "speed_name" is the empty string (""), then it will not -appear in the list of modifiers on the players speed (though the effect might still have an effect). + +This is the value used in the list of modifiers on a player's speed. It will default to the first +entry in "name" if it doesn't exist, and if neither one exists or if "speed_name" is the empty +string (""), then it will not appear in the list of modifiers on the players speed (though the +effect might still have an effect). ### Descriptions + ```C++ - "desc": ["XYZ"] - or - "desc": [ - "ABC", - "XYZ", - "123" - ] +"desc": ["XYZ"] +or +"desc": [ + "ABC", + "XYZ", + "123" +] ``` -Descriptions operate identically to the name field when picking which one to use. In general, descriptions -should be only 1 line. Stats and effects do not need to be included, and will be automatically generated -from the other effect data. Should a description line be the empty string ("") it will only display the -stat changes in the effect description. + +Descriptions operate identically to the name field when picking which one to use. In general, +descriptions should be only 1 line. Stats and effects do not need to be included, and will be +automatically generated from the other effect data. Should a description line be the empty string +("") it will only display the stat changes in the effect description. Descriptions also have a second field that can act as a modifier: + ```C++ - "part_descs": true - Defaults to false if not present +"part_descs": true - Defaults to false if not present ``` -If "part_descs" == true then descriptions are preceded by "Your X", where X is the body part name, meaning -the prior descriptions would appear as "Your left arm ABC". + +If "part_descs" == true then descriptions are preceded by "Your X", where X is the body part name, +meaning the prior descriptions would appear as "Your left arm ABC". Descriptions can also have a reduced form: + ```C++ - "reduced_desc": ["XYZ"] - or - "reduced_desc": [ - "ABC", - "XYZ", - "123" - ] +"reduced_desc": ["XYZ"] +or +"reduced_desc": [ + "ABC", + "XYZ", + "123" +] ``` -This is the description that will be used if an effect is reduced. By default this will use the normal description -if it doesn't exist. + +This is the description that will be used if an effect is reduced. By default this will use the +normal description if it doesn't exist. ### Rating + ```C++ - "rating": "good" - Defaults to "neutral" if missing +"rating": "good" - Defaults to "neutral" if missing ``` -This is used for how the messages when the effect is applied and removed are displayed. Also this affects "blood_analysis_description" (see below) field: effects with "good" rating will be colored green, effects with any other rating will be colored red when character conducts a blood analysis through some means. -Valid entries are: + +This is used for how the messages when the effect is applied and removed are displayed. Also this +affects "blood_analysis_description" (see below) field: effects with "good" rating will be colored +green, effects with any other rating will be colored red when character conducts a blood analysis +through some means. Valid entries are: + ```C++ "good" "neutral" @@ -164,154 +197,195 @@ Valid entries are: ``` ### Messages + ```C++ - "apply_message": "message", - "remove_message": "message" +"apply_message": "message", +"remove_message": "message" ``` -If the "apply_message" or "remove_message" fields exist, the respective message will be -displayed upon the addition or removal of the effect. Note: "apply_message" will only display -if the effect is being added, not if it is simply incrementing a current effect (so only new bites, etc.). + +If the "apply_message" or "remove_message" fields exist, the respective message will be displayed +upon the addition or removal of the effect. Note: "apply_message" will only display if the effect is +being added, not if it is simply incrementing a current effect (so only new bites, etc.). ### Memorial Log + ```C++ - "apply_memorial_log": "log", - "remove_memorial_log": "log" +"apply_memorial_log": "log", +"remove_memorial_log": "log" ``` -If the "apply_memorial_log" or "remove_memorial_log" fields exist, the game will add the -respective message to the memorial log on addition or removal of the effect. Similar to -the message fields the "apply_memorial_log" will only be added to the log for new effect additions. + +If the "apply_memorial_log" or "remove_memorial_log" fields exist, the game will add the respective +message to the memorial log on addition or removal of the effect. Similar to the message fields the +"apply_memorial_log" will only be added to the log for new effect additions. ### Resistances + ```C++ - "resist_trait": "NOPAIN", - "resist_effect": "flumed" +"resist_trait": "NOPAIN", +"resist_effect": "flumed" ``` + These fields are used to determine if an effect is being resisted or not. If the player has the -matching trait or effect then they are "resisting" the effect, which changes its effects and description. -Effects can only have one "resist_trait" and one "resist_effect" at a time. +matching trait or effect then they are "resisting" the effect, which changes its effects and +description. Effects can only have one "resist_trait" and one "resist_effect" at a time. ### Removes effects + ```C++ - "removes_effects": ["bite", "flu"] +"removes_effects": ["bite", "flu"] ``` -This field will cause an effect to automatically remove any other copies of the listed effects if they are present. -In the example above the placed effect would automatically cure any bite wounds or flu the player had. Any values here -automatically count for "blocks_effects" as well, no need to duplicate them there. + +This field will cause an effect to automatically remove any other copies of the listed effects if +they are present. In the example above the placed effect would automatically cure any bite wounds or +flu the player had. Any values here automatically count for "blocks_effects" as well, no need to +duplicate them there. ### Blocks effects + ```C++ - "blocks_effects": ["cold", "flu"] +"blocks_effects": ["cold", "flu"] ``` -This field will cause an effect to prevent the placement of the listed effects. In the example above the effect would -prevent the player from catching the cold or the flu (BUT WOULD NOT CURE ANY ONGOING COLDS OR FLUS). Any effects present -in "removes_effects" are automatically added to "blocks_effects", no need for manual duplication. + +This field will cause an effect to prevent the placement of the listed effects. In the example above +the effect would prevent the player from catching the cold or the flu (BUT WOULD NOT CURE ANY +ONGOING COLDS OR FLUS). Any effects present in "removes_effects" are automatically added to +"blocks_effects", no need for manual duplication. ### Effect limiters + ```C++ - "max_duration": 100, - "dur_add_perc": 150 - Defaults to 100% +"max_duration": 100, +"dur_add_perc": 150 - Defaults to 100% ``` -These are utilized when adding to currently existing effects. "max_duration" limits the overall duration of the effect. -"dur_add_perc" is the percentage value of the normal duration for adding to an existing. An example: -1) I add effect A to the player for 100 ticks. -2) I add effect A to the player again for 100 ticks. -Because the "dur_add_perc" = 150 in the example above, the second addition adds a total of 100 * 150% = 150 ticks, for -a total value of 250 ticks from the two. This can also be below 100%, and should be able to even be negative, leading to -future applications decreasing the overall time left. + +These are utilized when adding to currently existing effects. "max_duration" limits the overall +duration of the effect. "dur_add_perc" is the percentage value of the normal duration for adding to +an existing. An example: + +1. I add effect A to the player for 100 ticks. +2. I add effect A to the player again for 100 ticks. Because the "dur_add_perc" = 150 in the example + above, the second addition adds a total of 100 * 150% = 150 ticks, for a total value of 250 ticks + from the two. This can also be below 100%, and should be able to even be negative, leading to + future applications decreasing the overall time left. ### Intensities + Intensities are used to control effect effects, names, and descriptions. They are defined with: + ```C++ - "int_add_val": 2 - Defaults to 0! This means future applications will not increase intensity unless changed! - and/or - "int_decay_step": -2, - Defaults to -1 - "int_decay_tick": 10 - or - "int_dur_factor": 700 +"int_add_val": 2 - Defaults to 0! This means future applications will not increase intensity unless changed! +and/or +"int_decay_step": -2, - Defaults to -1 +"int_decay_tick": 10 +or +"int_dur_factor": 700 ``` -The first value is the amount an intensity will be incremented if adding to an already existing effect. As an example: -1) I add effect A to the player -2) I add effect A to the player again -Because "int_add_val" = 2, the second addition will change the effect intensity from 1 to 1 + 2 = 3. -NOTE: You must have at least one of the 3 intensity data sets for intensity to do anything! -"int_decay_step" and "int_decay_tick" require one another to do anything. If both exist then the game will automatically -increment the current effect intensities by "int_decay_step" every "int_decay_tick" ticks, capping the result at [1, "max_intensity"]. -This can be used to make effects automatically increase or decrease in intensity over time. +The first value is the amount an intensity will be incremented if adding to an already existing +effect. As an example: + +1. I add effect A to the player +2. I add effect A to the player again Because "int_add_val" = 2, the second addition will change the + effect intensity from 1 to 1 + 2 = 3. NOTE: You must have at least one of the 3 intensity data + sets for intensity to do anything! + +"int_decay_step" and "int_decay_tick" require one another to do anything. If both exist then the +game will automatically increment the current effect intensities by "int_decay_step" every +"int_decay_tick" ticks, capping the result at [1, "max_intensity"]. This can be used to make effects +automatically increase or decrease in intensity over time. -"int_dur_factor" overrides the other three intensities fields, and forces the intensity to be a number defined as -intensity = duration / "int_dur_factor" rounded up (so from 0 to "int_dur_factor" is intensity 1). +"int_dur_factor" overrides the other three intensities fields, and forces the intensity to be a +number defined as intensity = duration / "int_dur_factor" rounded up (so from 0 to "int_dur_factor" +is intensity 1). ### Permanence -An effect that is permanent does not lose duration with time. -That is, even if its duration is 1 turn, it will last until removed. + +An effect that is permanent does not lose duration with time. That is, even if its duration is 1 +turn, it will last until removed. + ```C++ - "permanent": true +"permanent": true ``` ### Miss messages + ```C++ - "miss_messages": [["Your blisters distract you", 1]] - or - "miss_messages": [ - ["Your blisters distract you", 1], - ["Your blisters don't like you", 10], - ] +"miss_messages": [["Your blisters distract you", 1]] +or +"miss_messages": [ + ["Your blisters distract you", 1], + ["Your blisters don't like you", 10], +] ``` + This will add the following miss messages at the given chances while the effect is in effect. ### Decay messages + ```C++ - "decay_messages": [["The jet injector's chemicals wear off. You feel AWFUL!", "bad"]] - or - "decay_messages": [ - ["The jet injector's chemicals wear off. You feel AWFUL!", "bad"], - ["OOGA-BOOGA. You feel AWFUL!", "bad"], - ] +"decay_messages": [["The jet injector's chemicals wear off. You feel AWFUL!", "bad"]] +or +"decay_messages": [ + ["The jet injector's chemicals wear off. You feel AWFUL!", "bad"], + ["OOGA-BOOGA. You feel AWFUL!", "bad"], +] ``` -The messages are matched to intensities, so the first message is for intensity 1, the second for intensity 2, and -so on. The messages will print whenever the intensity decreases to their matching intensity from a higher intensity, -whether through decay ticks or through "int_dur_factor". So if it decayed to intensity 2 from 3+ it would display -"OOGA-BOOGA. You feel AWFUL!" as a bad message to the player. + +The messages are matched to intensities, so the first message is for intensity 1, the second for +intensity 2, and so on. The messages will print whenever the intensity decreases to their matching +intensity from a higher intensity, whether through decay ticks or through "int_dur_factor". So if it +decayed to intensity 2 from 3+ it would display "OOGA-BOOGA. You feel AWFUL!" as a bad message to +the player. ### Targeting modifiers + ```C++ - "main_parts_only": true - Defaults to false +"main_parts_only": true - Defaults to false ``` + This automatically retargets any effect on a non-main part (hands, eyes, feet, etc.) to the matching main part (arms, head, legs, etc.). ### Effect modifiers + ```C++ - "pkill_addict_reduces": true, - Defaults to false - "pain_sizing": true, - Defaults to false - "hurt_sizing": true, - Defaults to false - "harmful_cough": true - Defaults to false +"pkill_addict_reduces": true, - Defaults to false +"pain_sizing": true, - Defaults to false +"hurt_sizing": true, - Defaults to false +"harmful_cough": true - Defaults to false ``` -"pkill_addict_reduces" makes a player's addiction to painkillers reduce the chance of the effect giving -them more pkill. "pain_sizing" and "hurt_sizing" cause large/huge mutations to affect the chance of pain -and hurt effects triggering. "harmful_cough" means that the coughs caused by this effect can hurt the player. + +"pkill_addict_reduces" makes a player's addiction to painkillers reduce the chance of the effect +giving them more pkill. "pain_sizing" and "hurt_sizing" cause large/huge mutations to affect the +chance of pain and hurt effects triggering. "harmful_cough" means that the coughs caused by this +effect can hurt the player. ### Morale + ```C++ - "morale": "morale_high" +"morale": "morale_high" ``` -Type of morale effect provided. Mandatory if there is a morale effect, must not be specified otherwise. + +Type of morale effect provided. Mandatory if there is a morale effect, must not be specified +otherwise. ### Effect effects + ```C++ - "base_mods" : { - arguments - }, - "scaling_mods": { - arguments - } +"base_mods" : { + arguments +}, +"scaling_mods": { + arguments +} ``` -This is where the real meat of the effect JSON definition lies. Each one can take a variety of arguments. -Decimals are valid but must be formatted as "0.X" or "-0.X". The game will round towards zero at the end -when calculating actually applied values + +This is where the real meat of the effect JSON definition lies. Each one can take a variety of +arguments. Decimals are valid but must be formatted as "0.X" or "-0.X". The game will round towards +zero at the end when calculating actually applied values Basic definitions: + ```C++ "X_amount" - Amount applied of X when effect is placed. Like apply messages it will only trigger on new effects "X_min" - Minimum amount of X applied when roll triggers @@ -324,6 +398,7 @@ Basic definitions: ``` Valid arguments: + ```C++ "str_mod" - Positive values raises stat, negative values lowers stat "dex_mod" - Positive values raises stat, negative values lowers stat @@ -445,73 +520,79 @@ Valid arguments: "healing_torso" - Percentage of healing value for torso "morale" - Amount of morale provided. Must be a single number (resistance not supported). - ``` + Each argument can also take either one or two values. + ```C++ - "thirst_min": [1] - or - "thirst_min": [1, 2] +"thirst_min": [1] +or +"thirst_min": [1, 2] ``` -If an effect is "resisted" (either through "resist_effect" or "resist_trait") then it will use the second -value. If there is only one value given it will always use that amount. -Base mods and Scaling mods: -While on intensity = 1 an effect will only have the basic effects of its "base_mods". However for each -additional intensity it gains it adds the value of each of its "scaling_mods" to the calculations. So: +If an effect is "resisted" (either through "resist_effect" or "resist_trait") then it will use the +second value. If there is only one value given it will always use that amount. + +Base mods and Scaling mods: While on intensity = 1 an effect will only have the basic effects of its +"base_mods". However for each additional intensity it gains it adds the value of each of its +"scaling_mods" to the calculations. So: + ```C++ Intensity 1 values = base_mods values Intensity 2 values = base_mods values + scaling_mods values Intensity 3 values = base_mods values + 2 * scaling_mods values Intensity 4 values = base_mods values + 3 * scaling_mods values ``` + and so on. -Special case: -The only special case is if base_mods' "X_chance_bot" + intensity * scaling_mods' "X_chance_bot" = 0 then it treats it -as if it were equal to 1 (i.e. trigger every time) +Special case: The only special case is if base_mods' "X_chance_bot" + intensity * scaling_mods' +"X_chance_bot" = 0 then it treats it as if it were equal to 1 (i.e. trigger every time) ## Example Effect + ```C++ - "type": "effect_type", - "id": "drunk", - "name": [ - "Tipsy", - "Drunk", - "Trashed", - "Wasted" - ], - "max_intensity": 4, - "apply_message": "You feel lightheaded.", - "int_dur_factor": 1000, - "miss_messages": [["You feel woozy.", 1]], - "morale": "morale_drunk", - "base_mods": { - "str_mod": [1], - "vomit_chance": [-43], - "sleep_chance": [-1003], - "sleep_min": [2500], - "sleep_max": [3500], - "morale": [ 5 ] - }, - "scaling_mods": { - "str_mod": [-0.67], - "per_mod": [-1], - "dex_mod": [-1], - "int_mod": [-1.42], - "vomit_chance": [21], - "sleep_chance": [501], - "morale": [ 10 ] - } -``` -First when "drunk" is applied to the player if they aren't already drunk it prints the message, -"You feel lightheaded". It also adds the "You feel woozy" miss message for as long as it is applied. -It has "int_dur_factor": 1000, meaning that its intensity will always be equal to its duration / 1000 rounded up, and -it has "max_intensity": 4 meaning the highest its intensity will go is 4 at a duration of 3000 or higher. -As it moves up through the different intensities, its name will change. Its description will simply display the stat -changes, with no additional description added. +"type": "effect_type", +"id": "drunk", +"name": [ + "Tipsy", + "Drunk", + "Trashed", + "Wasted" +], +"max_intensity": 4, +"apply_message": "You feel lightheaded.", +"int_dur_factor": 1000, +"miss_messages": [["You feel woozy.", 1]], +"morale": "morale_drunk", +"base_mods": { + "str_mod": [1], + "vomit_chance": [-43], + "sleep_chance": [-1003], + "sleep_min": [2500], + "sleep_max": [3500], + "morale": [ 5 ] +}, +"scaling_mods": { + "str_mod": [-0.67], + "per_mod": [-1], + "dex_mod": [-1], + "int_mod": [-1.42], + "vomit_chance": [21], + "sleep_chance": [501], + "morale": [ 10 ] +} +``` + +First when "drunk" is applied to the player if they aren't already drunk it prints the message, "You +feel lightheaded". It also adds the "You feel woozy" miss message for as long as it is applied. It +has "int_dur_factor": 1000, meaning that its intensity will always be equal to its duration / 1000 +rounded up, and it has "max_intensity": 4 meaning the highest its intensity will go is 4 at a +duration of 3000 or higher. As it moves up through the different intensities, its name will change. +Its description will simply display the stat changes, with no additional description added. As it moves up through the intensity levels its effects will be: + ```C++ Intensity 1 +1 STR @@ -544,7 +625,10 @@ Intensity 4 ``` ### Blood analysis description + ```C++ - "blood_analysis_description": "Minor Painkiller" +"blood_analysis_description": "Minor Painkiller" ``` -This description will be displayed for every effect which has this field when character conducts a blood analysis (for example, through Blood Analysis CBM). \ No newline at end of file + +This description will be displayed for every effect which has this field when character conducts a +blood analysis (for example, through Blood Analysis CBM). diff --git a/doc/FACTIONS.md b/doc/FACTIONS.md index 7ac113c732ec..0ce0c9a2fc95 100644 --- a/doc/FACTIONS.md +++ b/doc/FACTIONS.md @@ -3,78 +3,84 @@ An NPC faction looks like this: ```json - { - "type": "faction", - "id": "free_merchants", - "name": "The Free Merchants", - "likes_u": 30, - "respects_u": 30, - "known_by_u": false, - "size": 100, - "power": 100, - "food_supply": 115200, - "lone_wolf_faction": true, - "wealth": 75000000, - "currency": "FMCNote", - "relations": { - "free_merchants": { - "kill on sight": false, - "watch your back": true, - "share my stuff": true, - "guard your stuff": true, - "lets you in": true, - "defends your space": true, - "knows your voice": true - }, - "old_guard": { - "kill on sight": false, - "watch your back": true, - "share my stuff": false, - "guard your stuff": true, - "lets you in": true, - "defends your space": true, - "knows your voice": true - }, - "hells_raiders": { - "kill on sight": true - } - }, - "description": "A conglomeration of entrepreneurs and businessmen that stand together to hammer-out an existence through trade and industry." - }, +{ + "type": "faction", + "id": "free_merchants", + "name": "The Free Merchants", + "likes_u": 30, + "respects_u": 30, + "known_by_u": false, + "size": 100, + "power": 100, + "food_supply": 115200, + "lone_wolf_faction": true, + "wealth": 75000000, + "currency": "FMCNote", + "relations": { + "free_merchants": { + "kill on sight": false, + "watch your back": true, + "share my stuff": true, + "guard your stuff": true, + "lets you in": true, + "defends your space": true, + "knows your voice": true + }, + "old_guard": { + "kill on sight": false, + "watch your back": true, + "share my stuff": false, + "guard your stuff": true, + "lets you in": true, + "defends your space": true, + "knows your voice": true + }, + "hells_raiders": { + "kill on sight": true + } + }, + "description": "A conglomeration of entrepreneurs and businessmen that stand together to hammer-out an existence through trade and industry." +}, ``` -Field | Meaning --- | -- -`"type"` | string, must be `"faction"` -`"id"` | string, unique faction id -`"name"` | string, the faction's common name -`"likes_u"` | integer, the faction's starting opinion of the player. `"likes_u"` can be increased or decreased in play. If it goes below -10, members of the faction will be hostile. -`"respects_u"` | integer, the faction's starting opinionof the player. Has no meaningful effect in game and may be removed in the future. -`"known_by_u"` | boolean, whether the player has met members of the faction. Can be changed in play. Unknown factions will not be displayed in the faction menu. -`"size"` | integer, an approximate count of the members of the faction. Has no effect in play currently. -`"power"` | integer, an approximation of the faction's power. Has no effect in play currently. -`"food_supply"` | integer, the number of calories available to the faction. Has no effect in play currently. -`"wealth"` | integer, number of post-apocalyptic currency in cents that that faction has to purchase stuff. -`"currency"` | string, the item `"id"` of the faction's preferred currency. Faction shopkeeps will trade faction current at 100% value, for both selling and buying. -`"relations"` | dictionary, a description of how the faction sees other factions. See below -`"mon_faction"` | string, optional. The monster faction `"name"` of the monster faction that this faction counts as. Defaults to "human" if unspecified. -`"lone_wolf_faction"` | bool, optional. This is a proto/micro faction template that is used to generate 1-person factions for dynamically spawned NPCs, defaults to "false" if unspecified. +| Field | Meaning | +| --------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `"type"` | string, must be `"faction"` | +| `"id"` | string, unique faction id | +| `"name"` | string, the faction's common name | +| `"likes_u"` | integer, the faction's starting opinion of the player. `"likes_u"` can be increased or decreased in play. If it goes below -10, members of the faction will be hostile. | +| `"respects_u"` | integer, the faction's starting opinionof the player. Has no meaningful effect in game and may be removed in the future. | +| `"known_by_u"` | boolean, whether the player has met members of the faction. Can be changed in play. Unknown factions will not be displayed in the faction menu. | +| `"size"` | integer, an approximate count of the members of the faction. Has no effect in play currently. | +| `"power"` | integer, an approximation of the faction's power. Has no effect in play currently. | +| `"food_supply"` | integer, the number of calories available to the faction. Has no effect in play currently. | +| `"wealth"` | integer, number of post-apocalyptic currency in cents that that faction has to purchase stuff. | +| `"currency"` | string, the item `"id"` of the faction's preferred currency. Faction shopkeeps will trade faction current at 100% value, for both selling and buying. | +| `"relations"` | dictionary, a description of how the faction sees other factions. See below | +| `"mon_faction"` | string, optional. The monster faction `"name"` of the monster faction that this faction counts as. Defaults to "human" if unspecified. | +| `"lone_wolf_faction"` | bool, optional. This is a proto/micro faction template that is used to generate 1-person factions for dynamically spawned NPCs, defaults to "false" if unspecified. | ## Faction relations -Factions can have relations with each other that apply to each member of the faction. Faction relationships are not reciprocal: members of the Free Merchants will defend members of the Lobby Beggars, but members of the Lobby Beggars will not defend members of the Free Merchants. -Faction relationships are stored in a dictionary, with the dictionary keys being the name of the faction and the values being a second dictionary of boolean flags. All flags are optional and default to false. The faction with the dictionary is the acting faction and the other faction is the object faction. +Factions can have relations with each other that apply to each member of the faction. Faction +relationships are not reciprocal: members of the Free Merchants will defend members of the Lobby +Beggars, but members of the Lobby Beggars will not defend members of the Free Merchants. + +Faction relationships are stored in a dictionary, with the dictionary keys being the name of the +faction and the values being a second dictionary of boolean flags. All flags are optional and +default to false. The faction with the dictionary is the acting faction and the other faction is the +object faction. The flags have the following meanings: -Flag | Meaning --- | -- -`"kill on sight"` | Members of the acting faction are always hostile to members of the object faction. -`"watch your back"` | Members of the acting faction will treat attacks on members of the object faction as attacks on themselves. -`"share my stuff"` | Members of the acting faction will not object if members of the object faction take items owned by the acting faction. -`"guard your stuff"` | Members of the acting faction will object if someone takes items owned by the object faction. -`"lets you in"` | Members of the acting faction will not object if a member of the object faction enters territory controlled by the acting faction. -`"defends your space"` | Members of the acting faction will become hostile if someone enters territory controlled by the object faction. -`"knows your voice"` | Members of the acting faction will not comment on speech by members of the object faction. +| Flag | Meaning | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------- | +| `"kill on sight"` | Members of the acting faction are always hostile to members of the object faction. | +| `"watch your back"` | Members of the acting faction will treat attacks on members of the object faction as attacks on themselves. | +| `"share my stuff"` | Members of the acting faction will not object if members of the object faction take items owned by the acting faction. | +| `"guard your stuff"` | Members of the acting faction will object if someone takes items owned by the object faction. | +| `"lets you in"` | Members of the acting faction will not object if a member of the object faction enters territory controlled by the acting faction. | +| `"defends your space"` | Members of the acting faction will become hostile if someone enters territory controlled by the object faction. | +| `"knows your voice"` | Members of the acting faction will not comment on speech by members of the object faction. | So far, only `"kill on sight"`, `"knows your voice"`, and `"watch your back"` have been implemented. diff --git a/doc/GAME_BALANCE.md b/doc/GAME_BALANCE.md index 2e7ef664f27f..0284f437c0ea 100644 --- a/doc/GAME_BALANCE.md +++ b/doc/GAME_BALANCE.md @@ -1,4 +1,5 @@ # Stat system scaling: + Minimum stat: 0 (should only happen due to penalties, instant failure in most scenarios) Nominal stat: 8 ("average" person) @@ -7,14 +8,14 @@ Very high stat: 14 (realistic world class human, maximum cost-effective in charg Maximal stat: 20 (higher may be achievable, but we're not worried about balancing at that point.) - # Skill system scaling: + Minimum skill: 0 (no training) Maximum skill: 10 (requires regular training to maintain, "professional" level) - # Monster melee skill scaling: + Minimum skill: 0 (no melee potential; turret, fungal wall) Nominal skill: 4 (average critter; most zeds & giant insects) @@ -25,264 +26,416 @@ Very high skill: 8 (dangerous opponent; dark wyrm, vinebeast) Maximal skill: 10 (highest for balance purposes; jabberwock, tribot, shoggoth, gracken) - # Speeds: -Zombies are a bit faster than "shambling". Zombified versions of fast critters will remain fast, but in general the process slows the undead version. Further, under no circumstances should a zed be more than 50% faster than base character speed. Currently, this means "capped at 150". +Zombies are a bit faster than "shambling". Zombified versions of fast critters will remain fast, but +in general the process slows the undead version. Further, under no circumstances should a zed be +more than 50% faster than base character speed. Currently, this means "capped at 150". # Dodge System assumptions: + Dodge chance is based on attacker's melee skill and target's dex stat and dodge skill. Successful dodges negate the attack and impose a cumulative penalty on dodges within the same turn. ## Dodge Use Cases: -An individual with no skill and nominal stats in ideal circumstances against a basic opponent should occasionally be able to dodge. -An individual with no skill and nominal stats in ideal circumstances against a skilled opponent should rarely if ever be able to dodge. +An individual with no skill and nominal stats in ideal circumstances against a basic opponent should +occasionally be able to dodge. -An individual with world-class dodging ability, in ideal circumstances against a basic opponent should have a negligible chance of failure. +An individual with no skill and nominal stats in ideal circumstances against a skilled opponent +should rarely if ever be able to dodge. -An individual with world-class dodging ability, in ideal circumstances against a skilled opponent should have a moderate chance of failure. +An individual with world-class dodging ability, in ideal circumstances against a basic opponent +should have a negligible chance of failure. -The effect of increasing dodge skill has a growth rate with diminishing returns that accelerates sharply at the point where you move beyond the dodge a "regular" character is likely to achieve (7 and above) +An individual with world-class dodging ability, in ideal circumstances against a skilled opponent +should have a moderate chance of failure. -The balance of melee versus dodge should favor dodge which, after all, isn't effective against a wide variety of other types of attacks. +The effect of increasing dodge skill has a growth rate with diminishing returns that accelerates +sharply at the point where you move beyond the dodge a "regular" character is likely to achieve (7 +and above) -Even a world class dodger should not be able to dodge continuously when attacked many times a turn. +The balance of melee versus dodge should favor dodge which, after all, isn't effective against a +wide variety of other types of attacks. +Even a world class dodger should not be able to dodge continuously when attacked many times a turn. # MELEE WEAPONS: + ## To-Hit Bonuses -To-hit bonuses start at '-2' and are modified as follows for weapons that have the following properties: + +To-hit bonuses start at '-2' and are modified as follows for weapons that have the following +properties: ### Grip + Grip is a measure of how well you can control the weapon to quickly respond to situational changes. --1 - Particularly hard to grip items, (especially those that are innately slipper or very rounded with no obvious gripping edge) such as basketballs and barrels, or which are dangerous to hold because of very sharp edges, like scrap metal and broken glass. +-1 - Particularly hard to grip items, (especially those that are innately slipper or very rounded +with no obvious gripping edge) such as basketballs and barrels, or which are dangerous to hold +because of very sharp edges, like scrap metal and broken glass. -+0 - Any object that doesn't fall into one of the categories below. Examples include 2x4s, computer monitors, wires, stingers and clothing. Basically, anything that has a grippable component, but which is too thick, too thin, or too flimsy to grab comfortably in a way that can reliably control the object. ++0 - Any object that doesn't fall into one of the categories below. Examples include 2x4s, computer +monitors, wires, stingers and clothing. Basically, anything that has a grippable component, but +which is too thick, too thin, or too flimsy to grab comfortably in a way that can reliably control +the object. +1 - A weapon with a fairly solid grip, like a pipe, a rock, guitar neck, pool cue or a heavy stick. -+2 - A weapon with a dedicated grip shaped to the hand, like a sword, axe, knife, or police baton, or that is strapped to the body (or is a piece of the body). Fists would get a +2 bonus here, bringing them to "0" total, since none of the others would apply. ++2 - A weapon with a dedicated grip shaped to the hand, like a sword, axe, knife, or police baton, +or that is strapped to the body (or is a piece of the body). Fists would get a +2 bonus here, +bringing them to "0" total, since none of the others would apply. ### Length -Length allows more surface area for potential contact, and reduces the need to control the positioning of the body to guarantee a hit. It also allows the player to strike from a safer distance, allowing them to worry more about trying to hit without being hit in return, and allows for swings with larger arcs, making dodging such a strike more difficult. + +Length allows more surface area for potential contact, and reduces the need to control the +positioning of the body to guarantee a hit. It also allows the player to strike from a safer +distance, allowing them to worry more about trying to hit without being hit in return, and allows +for swings with larger arcs, making dodging such a strike more difficult. +0 - Any object without a length bonus. -+1 - Objects that, when held, extend over a foot (1/3 of a meter) in length from the hand. A normal American 12inch ruler is the handy boundary guide for when an item should switch over to a +1 bonus (the ruler, losing several inches when held, does not get one - unless you added a handle to it!). ++1 - Objects that, when held, extend over a foot (1/3 of a meter) in length from the hand. A normal +American 12inch ruler is the handy boundary guide for when an item should switch over to a +1 bonus +(the ruler, losing several inches when held, does not get one - unless you added a handle to it!). -+2 - An object that is over 3 feet in length from the point where it is held. Includes swords, spears, quarterstaffs, poles, and a lot of other stuff. ++2 - An object that is over 3 feet in length from the point where it is held. Includes swords, +spears, quarterstaffs, poles, and a lot of other stuff. ### Striking Surface -Some weapons need to strike in a certain way to be effective. Others are more difficult to use "incorrectly". --2 - Single-Point weapons - Picks, spears, syringes. Any weapon that has a single point that must contact the enemy in a specific way in order to deal a decent amount of damage. Also, weapons with difficult attack angles, like scythes, where the damaging part of the weapon is faced away from the enemy. +Some weapons need to strike in a certain way to be effective. Others are more difficult to use +"incorrectly". --1 - Line of damage weapons - Swords, knives, and other weapons that require a solid strike along a particular piece of the weapon, where the weapon can be said to have an attack angle, fall here. Weapons that have point attacks but are still effective without any solid hit, such as a nailboard, would also fall here. +-2 - Single-Point weapons - Picks, spears, syringes. Any weapon that has a single point that must +contact the enemy in a specific way in order to deal a decent amount of damage. Also, weapons with +difficult attack angles, like scythes, where the damaging part of the weapon is faced away from the +enemy. -+0 - attack-anywhere weapons - Clubs, pipes, maces, etc, where the weapon will be dealing full damage with a solid blow no matter how it is angled, because every surface is a striking surface. +-1 - Line of damage weapons - Swords, knives, and other weapons that require a solid strike along a +particular piece of the weapon, where the weapon can be said to have an attack angle, fall here. +Weapons that have point attacks but are still effective without any solid hit, such as a nailboard, +would also fall here. -+1 - Weapons that can still do significant damage even with glancing blows would fall here. Jagged tearing weapons and electric weapons like a stun baton would fall here. ++0 - attack-anywhere weapons - Clubs, pipes, maces, etc, where the weapon will be dealing full +damage with a solid blow no matter how it is angled, because every surface is a striking surface. + ++1 - Weapons that can still do significant damage even with glancing blows would fall here. Jagged +tearing weapons and electric weapons like a stun baton would fall here. ### Balance -A measure of how well-suited the item is for being swung/thrust/etc. This factors in overall balance of the weapon, weight is accounted for separately. --2 - Very clumsy or lopsided items ill-suited for swinging or thrusting. Characterized by requiring effort just to hold steady. frying pan or pot, chainsaw, chair, vacuum cleaner. +A measure of how well-suited the item is for being swung/thrust/etc. This factors in overall balance +of the weapon, weight is accounted for separately. + +-2 - Very clumsy or lopsided items ill-suited for swinging or thrusting. Characterized by requiring +effort just to hold steady. frying pan or pot, chainsaw, chair, vacuum cleaner. --1 - Balance of the object is uneven, but in a way that at least doesn't interfere with swinging. axes, sledgehammer, rifle, scythe, most polearms. +-1 - Balance of the object is uneven, but in a way that at least doesn't interfere with swinging. +axes, sledgehammer, rifle, scythe, most polearms. -+0 - Neutral balance, neither well nor poorly weighted for the typical use. Heavy stick, rock, pool stick, kitchen knives, claw hammer, metal pipe, crowbar, handguns. ++0 - Neutral balance, neither well nor poorly weighted for the typical use. Heavy stick, rock, pool +stick, kitchen knives, claw hammer, metal pipe, crowbar, handguns. -+1 - Well-balanced for swinging or stabbing. Baseball bat, golf club, swords, quarterstaff, knives. ++1 - Well-balanced for swinging or stabbing. Baseball bat, golf club, swords, quarterstaff, knives. ## Damage -Weapon's relative strength is based on an approximate formula involving its damage, to-hit, techniques and few other factors. + +Weapon's relative strength is based on an approximate formula involving its damage, to-hit, +techniques and few other factors. ### Damage per second -A melee's weapon damage per second (dps) is calculated past armor against a sample group of monsters with a range of dodge and armor values: a soldier zombie (low dodge, high bash and cut armor), a survivor zombie (medium dodge, some bash and cut armor), and a smoker zombie (high dodge, no armor). This should correctly weigh accuracy, criticals, and damage without over valuing any of them. -In code, this is calculated using the item::effective_dps() function, which takes a character and a monster. It calculates the relative accuracy of the character and weapon against the monster's defenses and determines the hit rate from a table lookup. It also determines the number of critical hits. Number of hits is hit rate * 10,000, and number of misses is 10,000 - number of hits. +A melee's weapon damage per second (dps) is calculated past armor against a sample group of monsters +with a range of dodge and armor values: a soldier zombie (low dodge, high bash and cut armor), a +survivor zombie (medium dodge, some bash and cut armor), and a smoker zombie (high dodge, no armor). +This should correctly weigh accuracy, criticals, and damage without over valuing any of them. + +In code, this is calculated using the item::effective_dps() function, which takes a character and a +monster. It calculates the relative accuracy of the character and weapon against the monster's +defenses and determines the hit rate from a table lookup. It also determines the number of critical +hits. Number of hits is hit rate * 10,000, and number of misses is 10,000 - number of hits. -For both critical and non-critical hits, average damage is calculated based on the weapon's stats and the user's skill. Monster armor absorbs the damage, and then the damage is multiplied by the number of hits: either critical hits for the critical hit case, or total hits - critical hits for the non critical hit case. If the weapon has the rapid strike technique, the total damage is halved, and then the average damage is recalculated, multiplied by 0.66, and absorbed by monster armor again to account for rapid strikes. +For both critical and non-critical hits, average damage is calculated based on the weapon's stats +and the user's skill. Monster armor absorbs the damage, and then the damage is multiplied by the +number of hits: either critical hits for the critical hit case, or total hits - critical hits for +the non critical hit case. If the weapon has the rapid strike technique, the total damage is halved, +and then the average damage is recalculated, multiplied by 0.66, and absorbed by monster armor again +to account for rapid strikes. -Number of moves is calculated as attack speed * ( number of misses + number of non-critical hits + number of critical hits ) for weapons without rapid strike, or attack speed * ( number of misses + number of non-critical hits / 2 + number of critical hits / 2 ) + attack speed / 2 * ( number of non-critical hits / 2 + number of critical hits / 2 ) for weapons without rapid strikes. +Number of moves is calculated as attack speed * ( number of misses + number of non-critical hits + +number of critical hits ) for weapons without rapid strike, or attack speed * ( number of misses + +number of non-critical hits / 2 + number of critical hits / 2 ) + attack speed / 2 * ( number of +non-critical hits / 2 + number of critical hits / 2 ) for weapons without rapid strikes. -Damage per second against a particular monster is total damage * 100 / number of moves (100 for the 100 moves/second). Overall dps is the average of the dps against the three reference monsters. +Damage per second against a particular monster is total damage * 100 / number of moves (100 for the +100 moves/second). Overall dps is the average of the dps against the three reference monsters. ### Critical hits -A double critical can occcur when a second hit roll is made against 1.5 * the monster's dodge. Double critical hits have a higher chance of occurring than normal critical hits. For each hit, the chance of achieving either a double critical hit or a normal critical hit is calculated, and then if a random number is less than the critical chance, the critical occurs. Both double and normal critical hits have the same effect, but the chance of them occurring is different. -**Note** The critical hit system is stupid and complicated and produces weird results. Double critical hits should have a chance of occuring when the original hit roll is more than 1 standard deviation above the mean, which is simple and faster to calculate than the current system. +A double critical can occcur when a second hit roll is made against 1.5 * the monster's dodge. +Double critical hits have a higher chance of occurring than normal critical hits. For each hit, the +chance of achieving either a double critical hit or a normal critical hit is calculated, and then if +a random number is less than the critical chance, the critical occurs. Both double and normal +critical hits have the same effect, but the chance of them occurring is different. + +**Note** The critical hit system is stupid and complicated and produces weird results. Double +critical hits should have a chance of occuring when the original hit roll is more than 1 standard +deviation above the mean, which is simple and faster to calculate than the current system. ### Other factors + Reach is worth +20% at reach 2, +35% at reach 3. A weapon that is usuable by a known martial art is worth +50%. ### Weapon tiers + Relative value should put the weapon into one of those categories: -<2 - Not weapons. Those items may be pressed into service, but are unlikely to be better than fists. Plastic bottles, rocks, boots. +<2 - Not weapons. Those items may be pressed into service, but are unlikely to be better than fists. +Plastic bottles, rocks, boots. 2-5 - Tools not meant to strike and improvised weapons. Two-by-fours, pointy sticks, pipes, hammers. -6-11 - Dangerous tools or crude dedicated weapons. Golf clubs, two-by-swords, wooden spears, knife spears, hatchets, switchblades, tonfas, quarterstaves. +6-11 - Dangerous tools or crude dedicated weapons. Golf clubs, two-by-swords, wooden spears, knife +spears, hatchets, switchblades, tonfas, quarterstaves. -12-15 - Good dedicated weapons or the most dangerous of tools. Wood and fire axes, steel spears, electric carvers, kukris, bokken, machetes, barbed wire bats. +12-15 - Good dedicated weapons or the most dangerous of tools. Wood and fire axes, steel spears, +electric carvers, kukris, bokken, machetes, barbed wire bats. -20-35 - Weapons of war, well designed to kill humans. Wakizashis, katanas, broadswords, zweihanders, combat knifes, battle axes, war hammers, maces, morningstars. +20-35 - Weapons of war, well designed to kill humans. Wakizashis, katanas, broadswords, zweihanders, +combat knifes, battle axes, war hammers, maces, morningstars. 35+ - Sci-fi stuff. Diamond katanas, monomolecular blades, lightsabers and chainswords. -Specific weapon balancing points: -20 - combat knifes -22 - short blades -24 - long blades, short axes, and short flails -26 - two handed blades, long axes, most spears -28 - two handed axes and polearms +Specific weapon balancing points: 20 - combat knifes 22 - short blades 24 - long blades, short axes, +and short flails 26 - two handed blades, long axes, most spears 28 - two handed axes and polearms 30 - combat spears Improvised weapons generally have about 75% of the value of a real weapon. ## Other melee balancing factors + ### Attack speed -Out of two weapons with same dpt, the faster one is generally better. -Faster weapons allow more damage granularity (less overkill), make it less likely to miss a turn (and thus dodge/block recharges) and make positioning easier. -Slower weapons will pierce armor better, but currently most enemies are very lightly armored. + +Out of two weapons with same dpt, the faster one is generally better. Faster weapons allow more +damage granularity (less overkill), make it less likely to miss a turn (and thus dodge/block +recharges) and make positioning easier. Slower weapons will pierce armor better, but currently most +enemies are very lightly armored. ### Damage type -At low skill, piercing damage suffers from scaling and bashing damage from damage limit due to low strength and skill. Cutting damage is not affected. -At high skill, bashing damage is generally the strongest, but still suffers from the damage limit. -Exotic damage types (currently only fire) do not scale with skills or crits. + +At low skill, piercing damage suffers from scaling and bashing damage from damage limit due to low +strength and skill. Cutting damage is not affected. At high skill, bashing damage is generally the +strongest, but still suffers from the damage limit. Exotic damage types (currently only fire) do not +scale with skills or crits. # RANGE WEAPONS + ## Automatic Fire -Guns with automatic fire are balanced around 1-second of cyclic fire, unless the cyclic or practical fire rate is less than 1 every second. Rates of fire less than 1 shot every second are increased to 2. + +Guns with automatic fire are balanced around 1-second of cyclic fire, unless the cyclic or practical +fire rate is less than 1 every second. Rates of fire less than 1 shot every second are increased +to 2. ## Magazines + ### Reload times -The overall balance is that magazines themselves are slow to reload whereas changing a magazine should be fast. For standard box magazines a default `reload_time` of 100 (per round) is appropriate with this value increasing for poor quality or extended magazines. Guns themselves should also specify `reload` of 100 (per magazine) unless their magazines are particularly awkward to reload (eg. ammo belts). The game logic intrinsically handles higher volume magazines consuming more time to attach to a gun so you need not consider this. + +The overall balance is that magazines themselves are slow to reload whereas changing a magazine +should be fast. For standard box magazines a default `reload_time` of 100 (per round) is appropriate +with this value increasing for poor quality or extended magazines. Guns themselves should also +specify `reload` of 100 (per magazine) unless their magazines are particularly awkward to reload +(eg. ammo belts). The game logic intrinsically handles higher volume magazines consuming more time +to attach to a gun so you need not consider this. ### Weight -Increases proportional to capacity and should have a comparable ratio to similar magazines. Consider the base item to be a 10-round .223 factory specification box magazine which has a capacity:weight of 1:10. Increase the ratio markedly for poor quality magazines or more slightly for extended magazines. Smaller calibers should use a lower ratio. The `material` should have some effect, with plastic magazines weighing less. + +Increases proportional to capacity and should have a comparable ratio to similar magazines. Consider +the base item to be a 10-round .223 factory specification box magazine which has a capacity:weight +of 1:10. Increase the ratio markedly for poor quality magazines or more slightly for extended +magazines. Smaller calibers should use a lower ratio. The `material` should have some effect, with +plastic magazines weighing less. ### Volume -Scaled based upon the capacity relative to the `stack_size` of the ammo. For example 223 has a `stack size` of 20 so for 10 and 30 round magazines the volume would be 1 and 2. Extended magazine should always have larger volume than the standard type and for very large drum magazines consider applying an extra penalty. By default most handgun magazines should be volume 1 and most rifle magazines volume 2. Ammo belts should not specify volume as this will be determined from their length. + +Scaled based upon the capacity relative to the `stack_size` of the ammo. For example 223 has a +`stack size` of 20 so for 10 and 30 round magazines the volume would be 1 and 2. Extended magazine +should always have larger volume than the standard type and for very large drum magazines consider +applying an extra penalty. By default most handgun magazines should be volume 1 and most rifle +magazines volume 2. Ammo belts should not specify volume as this will be determined from their +length. ### Reliability -Should be specified first considering the below and then scaled against any equivalent magazines. For example if an extended version of a magazine exists place it one rank below the standard capacity version. Damaged guns or magazines will further adversely affect reliability. -10 - **Perfectly reliable**. Factory specification or milspec only. Never extended magazines. Very rare. +Should be specified first considering the below and then scaled against any equivalent magazines. +For example if an extended version of a magazine exists place it one rank below the standard +capacity version. Damaged guns or magazines will further adversely affect reliability. -9 - **Reliable**. Failures only in burst fire. Factory or milspec magazines only. Never extended magazines. Uncommon. +10 - **Perfectly reliable**. Factory specification or milspec only. Never extended magazines. Very +rare. -8 - **Dependable**. Failures infrequently in any fire mode. Highest reliability possible for extended magazines and those crafted using gunsmithing tools. Most common. +9 - **Reliable**. Failures only in burst fire. Factory or milspec magazines only. Never extended +magazines. Uncommon. -7 - **Serviceable**. Fail infrequently in semi-automatic, more frequently in burst. Includes many extended and aftermarket gunsmithing tools. Common. +8 - **Dependable**. Failures infrequently in any fire mode. Highest reliability possible for +extended magazines and those crafted using gunsmithing tools. Most common. -6 - **Acceptable**. Failures can be problematic. Highest reliability possible for magazines crafted **without** gunsmithing tools. Includes most ammo belts. +7 - **Serviceable**. Fail infrequently in semi-automatic, more frequently in burst. Includes many +extended and aftermarket gunsmithing tools. Common. -5 - **Usable**. Failures can be problematic and more serious. Mostly poor quality hand-crafted magazines. +6 - **Acceptable**. Failures can be problematic. Highest reliability possible for magazines crafted +**without** gunsmithing tools. Includes most ammo belts. -<4 - **Poor**. Significant risk of catastrophic failure. Not applied by default to any item but can be acquired by damage or other factors. +5 - **Usable**. Failures can be problematic and more serious. Mostly poor quality hand-crafted +magazines. + +<4 - **Poor**. Significant risk of catastrophic failure. Not applied by default to any item but can +be acquired by damage or other factors. ### Rarity -Overall balance is that pistol magazines are twice as common as rifle magazines and that for guns that spawn with magazines these are always the standard capacity versions. Consider 9x19mm and .223 to be the defaults with everything else more rare. Some locations have more specific balance requirements: - -Location | Description | With guns | Damaged | Example -------------------|-----------------------------------------------------------|-----------|-----------|-------------------------- -Military site | Only source of milspec magazines and ammo belts | Never | Never | LW-56, .223 ammo belt -Gun store | Standard and extended capacity magazines | Never | Never | STANAG-30, Glock extended -Police armory | Mostly pistol magazines, especially 9x19mm, never extended| Sometimes | Never | Glock, MP5 magazine -SWAT truck | Police or military magazines, occasionally extended | Sometimes | Rarely | MP5 extended -Survivor basement | Anything except milspec weighted towards common types | Often | Sometimes | Saiga mag, M1911 extended -Military surplus | Older military magazines that are not current issue | Never | Rarely | M9 mag, STEN magazine -Pawn shop | Anything except milspec weighted towards unusual calibers | Never | Rarely | Makarov mag, AK-74 mag -Everywhere else | Predominately 9mm and 223. Always with standard magazine | Often | Sometimes | Ruger 223 mag, M1911 mag + +Overall balance is that pistol magazines are twice as common as rifle magazines and that for guns +that spawn with magazines these are always the standard capacity versions. Consider 9x19mm and .223 +to be the defaults with everything else more rare. Some locations have more specific balance +requirements: + +| Location | Description | With guns | Damaged | Example | +| ----------------- | ---------------------------------------------------------- | --------- | --------- | ------------------------- | +| Military site | Only source of milspec magazines and ammo belts | Never | Never | LW-56, .223 ammo belt | +| Gun store | Standard and extended capacity magazines | Never | Never | STANAG-30, Glock extended | +| Police armory | Mostly pistol magazines, especially 9x19mm, never extended | Sometimes | Never | Glock, MP5 magazine | +| SWAT truck | Police or military magazines, occasionally extended | Sometimes | Rarely | MP5 extended | +| Survivor basement | Anything except milspec weighted towards common types | Often | Sometimes | Saiga mag, M1911 extended | +| Military surplus | Older military magazines that are not current issue | Never | Rarely | M9 mag, STEN magazine | +| Pawn shop | Anything except milspec weighted towards unusual calibers | Never | Rarely | Makarov mag, AK-74 mag | +| Everywhere else | Predominately 9mm and 223. Always with standard magazine | Often | Sometimes | Ruger 223 mag, M1911 mag | ## Archery damage -Bow damage is based on the momentum achieved in the projectile. Since arrows and bolts have sharp cutting surfaces, the penetration and therefore damage achieved is based on the projectile's capacity for slicing through tissues. The arrow has a modifier based on construction, material and design, most critically centered around the effectiveness of the head. Base damage is calculated from momentum by taking momentum in Slug-foot-seconds, multiplying by 150 and subtracting 32. This was arrived at by taking well-regarded bowhunting guidelines and determining the damage numbers necessary for a kill of various game on a critical hit, see tests/archery_damage_test.cpp for details. + +Bow damage is based on the momentum achieved in the projectile. Since arrows and bolts have sharp +cutting surfaces, the penetration and therefore damage achieved is based on the projectile's +capacity for slicing through tissues. The arrow has a modifier based on construction, material and +design, most critically centered around the effectiveness of the head. Base damage is calculated +from momentum by taking momentum in Slug-foot-seconds, multiplying by 150 and subtracting 32. This +was arrived at by taking well-regarded bowhunting guidelines and determining the damage numbers +necessary for a kill of various game on a critical hit, see tests/archery_damage_test.cpp for +details. ## Ammo stats + ### Base Damage -The damage (**Dmg**) of firearm ammunition starts with the square root of a round's muzzle energy in joules (**Energy, J**) rounded to the nearest integer with an arbitrary increase or decrease to account for terminal ballistics. These numbers are modified depending on certain criteria (see Adjustment Criteria, below). Damage of handloaded ammo is set to 92% (rounded down) of their factory counterparts. A similar system for calculating recoil is planned but not currently being worked on. The figures used to calculate stats and any other relevant information are presented in table below. + +The damage (**Dmg**) of firearm ammunition starts with the square root of a round's muzzle energy in +joules (**Energy, J**) rounded to the nearest integer with an arbitrary increase or decrease to +account for terminal ballistics. These numbers are modified depending on certain criteria (see +Adjustment Criteria, below). Damage of handloaded ammo is set to 92% (rounded down) of their factory +counterparts. A similar system for calculating recoil is planned but not currently being worked on. +The figures used to calculate stats and any other relevant information are presented in table below. ### Base Barrel Length -Each cartridge also has a Base Barrel Length (**Base Brl**) listed; this determines the damage for the connected guns. A firearm has its damage modifier determined by it's real life barrel length; for every three inches between it and the listed baseline here, the gun takes a 1 point bonus or penalty, rounding to the nearest modifier. For example, a .45 ACP gun with a 7 inch barrel would get a +1 bonus (against a baseline of 5 inches). - -Ammo ID | Description | Energy, J | Dmg | Base Brl | Applied Modifiers / Comments | --------------------|-----------------------------|-----------|-----|----------|------------------------------- -.22 CB | 18gr CB bullet | 39 | 6 | 7.87in | | -.22LR | 40gr unjacketed bullet | 141 | 12 | 6in | | -.22LR FMJ | 30gr FMJ bullet | 277 | 17 | 6in | | -.32 ACP | 60gr JHP bullet | 218 | 15 | 4in | | -7.62x25mm | 85gr JHP bullet | 544 | 23 | 4.7in | | -7.62x25mm Type P | 120gr bullet | 245 | 15 | 9.6in | Fired from the Type 64 SMG; need more data here | -9x18mm 57-N-181S | 93gr FMJ bullet | 251 | 16 | 3.8in | | -9x18mm SP-7 | 93gr bullet | 417 | 20 | 3.8in | | -9x18mm RG028 | 93gr hardened steel core bullet | 317 | 18 | 3.8in | damage reduced by 4 | -9x19mm FMJ | 115gr FMJ bullet | 420 | 24 | 5.9in | | -9x19mm JHP | 115gr JHP bullet | 533 | 23 | 5.9in |damage increased by 3 | -9x19mm +P | 115gr JHP bullet | 632 | 25 | 5.9in | | -9x19mm +P+ | 115gr JHP bullet | 678 | 26 | 5.9in | | -.38 Special | 130gr FMJ bullet | 256 | 16 | 4in | | -.38 FMJ | 130gr FMJ bullet | 256 | 16 | 4in | | -.38 Super | 147gr JHP bullet | 660 | 26 | 4in | | -10mm Auto | 180gr FMJ bullet | 960 | 31 | 4in | | -.40 S&W | 135gr JHP bullet | 575 | 24 | 4in | | -.40 FMJ | 180gr FMJ bullet | 598 | 24 | 4in | | -.44 Magnum | 240gr JHP bullet | 1570 | 40 | 7.5in | | -.45 ACP JHP | 185gr JHP bullet | 614 | 25 | 5in | | -.45 ACP FMJ | 230gr FMJ bullet | 447 | 21 | 5in | | -.45 ACP +P | 200gr JHP bullet | 702 | 26 | 5in | | -.454 Casull | 300gr JSP bullet | 2459 | 50 | 7.5in | | -.45 Colt JHP | 250gr JHP bullet | 610 | 25 | 7.5in | | -.500 S&W Magnum | 500gr bullet | 3056 | 55 | 8.4in | | -4.6x30mm | 31gr copper plated steel bullet | 505 | 22 | 7.1in | damage reduced by 4 | -5.7x28mm SS190 | 31gr AP FMJ bullet | 534 | 23 | 10.4in | damage reduced by 3 | -7.62x39mm | 123gr FMJ bullet | 2179 | 46 | 16.3in | | -7.62x39mm 57-N-231 | 121.9gr steel core FMJ bullet | 2036 | 45 | 16.3in | | -7.62x39mm M67 | 123gr FMJ bullet | 2141 | 46 | 16.3in | TODO | -5.45x39mm 7N10 | 56gr FMJ bullet | 1402 | 37 | 16.3in | damage increased by 3 | -5.45x39mm 7N22 | 57gr steel core FMJ bullet | 1461 | 38 | 16.3in | | -.223 Remington | 36gr JHP bullet | 1524 | 39 | 20in |Uses 5.56 NATO barrel baseline; damage increased by 5 | -5.56x45mm M855A1 | 62gr copper core FMJBT bullet | 1843 | 43 | 20in | | -.300BLK supersonic | 125gr OTM | 1840 | 43 | 16in | -,300BLK subsonic | 220gr OTM | 675 | 26 | 16in | subsonic -7.62x54mmR | 150gr FMJ bullet | 3629 | 60 | 28in | | -.308 Winchester | 168gr hollow point bullet | 3570 | 60 | 24in | | -7.62x51mm NATO M80 | 147gr FMJ bullet | 3304 | 57 | 24in | | -7.62x51mm NATO M62 | 142gr tracer bullet | 3232 | 57 | 24in | Belt with 1/5 tracer rounds | -.270 Winchester | 130gr soft point bullet | 3663 | 61 | 24in | | -.30-06 Springfield | 165gr soft point bullet | 3894 | 62 | 24in | damage increased by 4 | -.30-06 M2 | 165.7gr AP bullet | 3676 | 60 | 24in | damage reduced by 10 | -.30-06 M14A1 | Incendiary ammunition | 3894 | 62 | 24in | damage reduced by 10 | -.45-70 Govt. | 300gr soft point bullet | 3867 | 66 | 24in | damage increased by 4 | -.300 Winchester Magnum | 220gr JHP bullet | 5299 | 73 | 24in | damage increased by 5 | -.700 NX | 1000gr JSP bullet | 12100 | 110 | 28in | | -.50 BMG Ball | 750gr FMJ-BT bullet | 17083 | 131 | 45in | | -.50 BMG M33 Ball | 706.7gr bullet | 18013 | 134 | 45in | | -.50 BMG M903 SLAP | 355gr tungsten AP bullet | 17083 | 131 | 45in | Can't be used with M107A1 | -.410 000 shot | 5 000 pellets | 1530 | 39 | 18in | | - -###Adjustment Criteria -If the resulting base damage is below specific thresholds, apply one of three multipliers. If the base damage is less than 20, the multiplier is 1.333. Else, if the base damage less than 30, the multiplier is 1.222. Else, if the base damage is less than 40, the multiplier is 1.111. Ammunition with damage of 40 or higher will generally have no arbitrary multiplier given to its basic variant. - -For liminal cases where the base damage is 20, 30, or 40 there is room for discretion regarding which balance increase to apply, if any. Discretion should be exercised based on which solution makes that ammunition distinct from other ammunition of similar power, as having two different ammotypes with identical power should be avoided. - -As for terminal ballistics, hollowpoints variant should be at least 25% more effective against a completely unarmored target, in order for the difference to be considered relevant. Conversely, the base FMJ variation should have a combined damage and armor penetration whose total is at least 15% greater than the damage of the hollowpoint variant. This recommendation will inform how much armor penetration the two variants should have. Armor-piercing variants have seven-eigths the damage of the standard FMJ variant, and enough penetration to make the combined value 30% higher than the damage of hollowpoint. - -The relative combined damage plus armor penetration for each variant can likewise be summarized as follows: + +Each cartridge also has a Base Barrel Length (**Base Brl**) listed; this determines the damage for +the connected guns. A firearm has its damage modifier determined by it's real life barrel length; +for every three inches between it and the listed baseline here, the gun takes a 1 point bonus or +penalty, rounding to the nearest modifier. For example, a .45 ACP gun with a 7 inch barrel would get +a +1 bonus (against a baseline of 5 inches). + +| Ammo ID | Description | Energy, J | Dmg | Base Brl | Applied Modifiers / Comments | +| ---------------------- | ------------------------------- | --------- | --- | -------- | ----------------------------------------------------- | +| .22 CB | 18gr CB bullet | 39 | 6 | 7.87in | | +| .22LR | 40gr unjacketed bullet | 141 | 12 | 6in | | +| .22LR FMJ | 30gr FMJ bullet | 277 | 17 | 6in | | +| .32 ACP | 60gr JHP bullet | 218 | 15 | 4in | | +| 7.62x25mm | 85gr JHP bullet | 544 | 23 | 4.7in | | +| 7.62x25mm Type P | 120gr bullet | 245 | 15 | 9.6in | Fired from the Type 64 SMG; need more data here | +| 9x18mm 57-N-181S | 93gr FMJ bullet | 251 | 16 | 3.8in | | +| 9x18mm SP-7 | 93gr bullet | 417 | 20 | 3.8in | | +| 9x18mm RG028 | 93gr hardened steel core bullet | 317 | 18 | 3.8in | damage reduced by 4 | +| 9x19mm FMJ | 115gr FMJ bullet | 420 | 24 | 5.9in | | +| 9x19mm JHP | 115gr JHP bullet | 533 | 23 | 5.9in | damage increased by 3 | +| 9x19mm +P | 115gr JHP bullet | 632 | 25 | 5.9in | | +| 9x19mm +P+ | 115gr JHP bullet | 678 | 26 | 5.9in | | +| .38 Special | 130gr FMJ bullet | 256 | 16 | 4in | | +| .38 FMJ | 130gr FMJ bullet | 256 | 16 | 4in | | +| .38 Super | 147gr JHP bullet | 660 | 26 | 4in | | +| 10mm Auto | 180gr FMJ bullet | 960 | 31 | 4in | | +| .40 S&W | 135gr JHP bullet | 575 | 24 | 4in | | +| .40 FMJ | 180gr FMJ bullet | 598 | 24 | 4in | | +| .44 Magnum | 240gr JHP bullet | 1570 | 40 | 7.5in | | +| .45 ACP JHP | 185gr JHP bullet | 614 | 25 | 5in | | +| .45 ACP FMJ | 230gr FMJ bullet | 447 | 21 | 5in | | +| .45 ACP +P | 200gr JHP bullet | 702 | 26 | 5in | | +| .454 Casull | 300gr JSP bullet | 2459 | 50 | 7.5in | | +| .45 Colt JHP | 250gr JHP bullet | 610 | 25 | 7.5in | | +| .500 S&W Magnum | 500gr bullet | 3056 | 55 | 8.4in | | +| 4.6x30mm | 31gr copper plated steel bullet | 505 | 22 | 7.1in | damage reduced by 4 | +| 5.7x28mm SS190 | 31gr AP FMJ bullet | 534 | 23 | 10.4in | damage reduced by 3 | +| 7.62x39mm | 123gr FMJ bullet | 2179 | 46 | 16.3in | | +| 7.62x39mm 57-N-231 | 121.9gr steel core FMJ bullet | 2036 | 45 | 16.3in | | +| 7.62x39mm M67 | 123gr FMJ bullet | 2141 | 46 | 16.3in | TODO | +| 5.45x39mm 7N10 | 56gr FMJ bullet | 1402 | 37 | 16.3in | damage increased by 3 | +| 5.45x39mm 7N22 | 57gr steel core FMJ bullet | 1461 | 38 | 16.3in | | +| .223 Remington | 36gr JHP bullet | 1524 | 39 | 20in | Uses 5.56 NATO barrel baseline; damage increased by 5 | +| 5.56x45mm M855A1 | 62gr copper core FMJBT bullet | 1843 | 43 | 20in | | +| .300BLK supersonic | 125gr OTM | 1840 | 43 | 16in | | +| ,300BLK subsonic | 220gr OTM | 675 | 26 | 16in | subsonic | +| 7.62x54mmR | 150gr FMJ bullet | 3629 | 60 | 28in | | +| .308 Winchester | 168gr hollow point bullet | 3570 | 60 | 24in | | +| 7.62x51mm NATO M80 | 147gr FMJ bullet | 3304 | 57 | 24in | | +| 7.62x51mm NATO M62 | 142gr tracer bullet | 3232 | 57 | 24in | Belt with 1/5 tracer rounds | +| .270 Winchester | 130gr soft point bullet | 3663 | 61 | 24in | | +| .30-06 Springfield | 165gr soft point bullet | 3894 | 62 | 24in | damage increased by 4 | +| .30-06 M2 | 165.7gr AP bullet | 3676 | 60 | 24in | damage reduced by 10 | +| .30-06 M14A1 | Incendiary ammunition | 3894 | 62 | 24in | damage reduced by 10 | +| .45-70 Govt. | 300gr soft point bullet | 3867 | 66 | 24in | damage increased by 4 | +| .300 Winchester Magnum | 220gr JHP bullet | 5299 | 73 | 24in | damage increased by 5 | +| .700 NX | 1000gr JSP bullet | 12100 | 110 | 28in | | +| .50 BMG Ball | 750gr FMJ-BT bullet | 17083 | 131 | 45in | | +| .50 BMG M33 Ball | 706.7gr bullet | 18013 | 134 | 45in | | +| .50 BMG M903 SLAP | 355gr tungsten AP bullet | 17083 | 131 | 45in | Can't be used with M107A1 | +| .410 000 shot | 5 000 pellets | 1530 | 39 | 18in | | + +###Adjustment Criteria If the resulting base damage is below specific thresholds, apply one of three +multipliers. If the base damage is less than 20, the multiplier is 1.333. Else, if the base damage +less than 30, the multiplier is 1.222. Else, if the base damage is less than 40, the multiplier is +1.111. Ammunition with damage of 40 or higher will generally have no arbitrary multiplier given to +its basic variant. + +For liminal cases where the base damage is 20, 30, or 40 there is room for discretion regarding +which balance increase to apply, if any. Discretion should be exercised based on which solution +makes that ammunition distinct from other ammunition of similar power, as having two different +ammotypes with identical power should be avoided. + +As for terminal ballistics, hollowpoints variant should be at least 25% more effective against a +completely unarmored target, in order for the difference to be considered relevant. Conversely, the +base FMJ variation should have a combined damage and armor penetration whose total is at least 15% +greater than the damage of the hollowpoint variant. This recommendation will inform how much armor +penetration the two variants should have. Armor-piercing variants have seven-eigths the damage of +the standard FMJ variant, and enough penetration to make the combined value 30% higher than the +damage of hollowpoint. + +The relative combined damage plus armor penetration for each variant can likewise be summarized as +follows: + 1. Hollowpoints are considered to have 100% combined damage (example: 100 damage, 0 arpen) -2. Standard/FMJ variants are considered to have 115% combined damage, 80% damage and 35% arpen (example: 80 damage, 35 arpen) -3. AP variants are considered to have 130% combined damage, 70% damage and 60% arpen (example: 70 damage, 60 arpen) +2. Standard/FMJ variants are considered to have 115% combined damage, 80% damage and 35% arpen + (example: 80 damage, 35 arpen) +3. AP variants are considered to have 130% combined damage, 70% damage and 60% arpen (example: 70 + damage, 60 arpen) # LIQUIDS: -Multi-charge items are weighed by the charge/use. If you have an item that contains 40 uses, it'll weigh 40x as much (when found in-game) as you entered in the JSON. Liquids are priced by the 250mL unit, but handled in containers. This can cause problems if you create something that comes in (say) a gallon jug (15 charges) and price it at the cost of a jug's worth: it'll be 15x as expensive as intended. -To that end, here's a list of containers with non-one volume. If you have something spawn in 'em, divide the "shelf" price by this value to arrive at the correct price to list in the JSON. +Multi-charge items are weighed by the charge/use. If you have an item that contains 40 uses, it'll +weigh 40x as much (when found in-game) as you entered in the JSON. Liquids are priced by the 250mL +unit, but handled in containers. This can cause problems if you create something that comes in (say) +a gallon jug (15 charges) and price it at the cost of a jug's worth: it'll be 15x as expensive as +intended. + +To that end, here's a list of containers with non-one volume. If you have something spawn in 'em, +divide the "shelf" price by this value to arrive at the correct price to list in the JSON. - plastic bottle: 2 @@ -297,6 +450,6 @@ To that end, here's a list of containers with non-one volume. If you have somet - gallon jug: 15 # Diamond weapons -Diamond weapons should be uniform in their CVD machine requirements. -Coal requirements are `floor((weapon_volume+1)/2)*25`. -Hydrogen requirements are `coal_requirements/2.5`. + +Diamond weapons should be uniform in their CVD machine requirements. Coal requirements are +`floor((weapon_volume+1)/2)*25`. Hydrogen requirements are `coal_requirements/2.5`. diff --git a/doc/GUIDE_COMESTIBLES.md b/doc/GUIDE_COMESTIBLES.md index 993763cfe5da..6465417c126c 100644 --- a/doc/GUIDE_COMESTIBLES.md +++ b/doc/GUIDE_COMESTIBLES.md @@ -1,44 +1,56 @@ # Guide to add Comestibles -There are a large number of files in `json/items/comestibles`, and this guide will help you decide where to put your new comestible! +There are a large number of files in `json/items/comestibles`, and this guide will help you decide +where to put your new comestible! ## List of special comestibles: -`med.json` -- comestible that has an addiction effect besides alcohol and caffeine, plus bandages and antiseptic type items. + +`med.json` -- comestible that has an addiction effect besides alcohol and caffeine, plus bandages +and antiseptic type items. `mre.json` -- items and comestibles related to MREs `mutagen.json` -- comestible that has any mutagen effect -`carnivore.json` -- item that would normally be butchered from an animal or monster, and their cooked versions. examples: chunks of meat, tainted bones, boiled stomach +`carnivore.json` -- item that would normally be butchered from an animal or monster, and their +cooked versions. examples: chunks of meat, tainted bones, boiled stomach `protein.json` -- comestibles based on protein powder -`spice.json` -- comestibles that normally do not have nutrients, but are used to flavor a dish. examples: salt, thyme, black pepper +`spice.json` -- comestibles that normally do not have nutrients, but are used to flavor a dish. +examples: salt, thyme, black pepper `frozen.json` -- comestibles best eaten frozen `brewing.json` -- items used in the brewing process ## List of normal comestibles, in order of priority: -When you have a comestible you want to add to the files, just go down this list, and the first filename you see in the list that matches the criteria is your choice! + +When you have a comestible you want to add to the files, just go down this list, and the first +filename you see in the list that matches the criteria is your choice! ### Liquid `alcohol.json` -- "Drink" comestible with alcohol addiction -`soup.json` -- "Drink" comestible which is a soup. This is more of a "food" than a drink - you primarily want the calories from this +`soup.json` -- "Drink" comestible which is a soup. This is more of a "food" than a drink - you +primarily want the calories from this -`drink.json` -- "Drink" comestible. This is your drink of choice when you're thirsty! examples: tea, juice, water +`drink.json` -- "Drink" comestible. This is your drink of choice when you're thirsty! examples: tea, +juice, water -`drink_other.json` -- "Drink" comestible that does not fit any other criteria. example: vinegar, mustard +`drink_other.json` -- "Drink" comestible that does not fit any other criteria. example: vinegar, +mustard ### Solid `junkfood.json` -- comestible with the "junk" material. examples: cake, sugary cereal, nachos -`sandwich.json` -- a "sandwich" is generally two slices of "bread" with something in between. examples: BLT, PB&J sandwich, fish sandwich +`sandwich.json` -- a "sandwich" is generally two slices of "bread" with something in between. +examples: BLT, PB&J sandwich, fish sandwich -`offal_dishes.json` -- comestible made of various offals. the offal types are: liver, brain, kidney, sweetbread, stomach. This must be the primary part of the dish. +`offal_dishes.json` -- comestible made of various offals. the offal types are: liver, brain, kidney, +sweetbread, stomach. This must be the primary part of the dish. `seed.json` -- seeds @@ -68,4 +80,4 @@ When you have a comestible you want to add to the files, just go down this list, `nuts.json` -- a nut or made of nuts -`other.json` -- if you made it here, your comestible doesn't fit any other category! \ No newline at end of file +`other.json` -- if you made it here, your comestible doesn't fit any other category! diff --git a/doc/IN_REPO_MODS.md b/doc/IN_REPO_MODS.md index 04f8736f74e4..1a3738b5771e 100644 --- a/doc/IN_REPO_MODS.md +++ b/doc/IN_REPO_MODS.md @@ -1,59 +1,98 @@ # Getting Mods Into The Repository -Cataclysm: Dark Days Ahead is not only moddable, but ships with a number of mods available for users to select from even without having to obtain mods from a third party source. +Cataclysm: Dark Days Ahead is not only moddable, but ships with a number of mods available for users +to select from even without having to obtain mods from a third party source. ## Why have in-repo mods? The benefits of having mods in the repository include: -* Visibility to a large number of users and potential contributors -* The ability to use the CleverRaven issue tracker to report problems, as well as manage pull requests for adding to or fixing mods in the repository -* Mods in the CleverRaven repository that demonstrate usage of a game feature which exists only for mods (i.e. not used by the core DDA game itself) help ensure that feature stays present in the game. +- Visibility to a large number of users and potential contributors +- The ability to use the CleverRaven issue tracker to report problems, as well as manage pull + requests for adding to or fixing mods in the repository +- Mods in the CleverRaven repository that demonstrate usage of a game feature which exists only for + mods (i.e. not used by the core DDA game itself) help ensure that feature stays present in the + game. There are however things that might be expected but are not guaranteed: -* Guarantee of maintenance of content -- core devs are mostly focused on the main game itself; although some might pick up mods as a side task, people who continue working on the core game tend to like the feel of the core game. -* Guarantee of maintenance of used features -- over the course of development it may become impossible to keep a feature, due to performance needs or maintenance burden. -* Guarantee of sole authorship -- once in the repository, the mod is considered community content. While the developers might defer to an active curator of a mod, if they become inactive anyone else can step forward. +- Guarantee of maintenance of content -- core devs are mostly focused on the main game itself; + although some might pick up mods as a side task, people who continue working on the core game tend + to like the feel of the core game. +- Guarantee of maintenance of used features -- over the course of development it may become + impossible to keep a feature, due to performance needs or maintenance burden. +- Guarantee of sole authorship -- once in the repository, the mod is considered community content. + While the developers might defer to an active curator of a mod, if they become inactive anyone + else can step forward. ## What kind of mods can be in the CleverRaven repository? There are three primary categories of mods: -* Content mods, which provide some kind of distinct experience from the core Dark Days Ahead game. This could be a change to lore, a change to a specific part of gameplay. -* User Experience (UX) mods, which alter the look and feel of the game interface itself. -* Development mods, which aren't "mods" in the typical sense but are instead there to ease the transition between "incomplete feature" and "complete feature", when a feature in the core game is sufficiently incomplete that the developers believe it needs to be optional to minimize disruption to players. +- Content mods, which provide some kind of distinct experience from the core Dark Days Ahead game. + This could be a change to lore, a change to a specific part of gameplay. +- User Experience (UX) mods, which alter the look and feel of the game interface itself. +- Development mods, which aren't "mods" in the typical sense but are instead there to ease the + transition between "incomplete feature" and "complete feature", when a feature in the core game is + sufficiently incomplete that the developers believe it needs to be optional to minimize disruption + to players. ## What is necessary for a mod to be included in the repository? -The most crucial criteria for a mod to be in the CleverRaven repository is that it has someone acting as a curator. This ensures that there is someone who is keeping an eye out for possible problems with the mod, and helping steer its development so that it continues to develop in accordance with its design purpose. +The most crucial criteria for a mod to be in the CleverRaven repository is that it has someone +acting as a curator. This ensures that there is someone who is keeping an eye out for possible +problems with the mod, and helping steer its development so that it continues to develop in +accordance with its design purpose. Furthermore, there are additional criteria: -* Content mods need to be providing some kind of curated experience. Either they introduce a set of locations, encounters, equipment, or progression mechanisms that do not fit the style of the core game, or they in some fashion modify the game according to some well-defined concept. -* * Mods which do not qualify as curated experiences: Grab bag mods with no defined purpose (i.e. adding a bunch of random guns), "settings" mods that just turn off a possibly undesired but working feature (acid ants). -* Development mods need to have an associated work-in-progress feature that they exist to mitigate. +- Content mods need to be providing some kind of curated experience. Either they introduce a set of + locations, encounters, equipment, or progression mechanisms that do not fit the style of the core + game, or they in some fashion modify the game according to some well-defined concept. +- + - Mods which do not qualify as curated experiences: Grab bag mods with no defined purpose (i.e. + adding a bunch of random guns), "settings" mods that just turn off a possibly undesired but + working feature (acid ants). +- Development mods need to have an associated work-in-progress feature that they exist to mitigate. ## What are the responsibilities of a mod curator? -A mod curator's role is to curate additions to mods and ensure they fit the concept of the mod. Curators are also responsible for at least acknowledging bug reports related to the mod: while curators don't have to personally manage every bugfix, if a bug is reported, the curator should be around to comment and help to find someone to fix it. +A mod curator's role is to curate additions to mods and ensure they fit the concept of the mod. +Curators are also responsible for at least acknowledging bug reports related to the mod: while +curators don't have to personally manage every bugfix, if a bug is reported, the curator should be +around to comment and help to find someone to fix it. -It's important to understand that if a mod is in the repository, it is expected that people other than the curator are going to contribute to it, as with anything. On github, mod curators should Approve or Request Changes on PRs to the mod. If the curator has approved it, developers with merge permissions will treat that as a request to merge the changes. +It's important to understand that if a mod is in the repository, it is expected that people other +than the curator are going to contribute to it, as with anything. On github, mod curators should +Approve or Request Changes on PRs to the mod. If the curator has approved it, developers with merge +permissions will treat that as a request to merge the changes. ## When do mods get removed? -Mods that have no curator or have proven to be consistently some type of maintenance burden are potentially subject to removal. Additionally, mods which had a purpose which is no longer relevant (development mods whose accompanying feature has been finished) will generally be removed once they're no longer deemed necessary. If a curator can't be reached for comment on a bugfix or review on a PR'd change for about a month, and hasn't left any indication of when they'll be back, developers will assume they've left the project, and the mod is orphaned. +Mods that have no curator or have proven to be consistently some type of maintenance burden are +potentially subject to removal. Additionally, mods which had a purpose which is no longer relevant +(development mods whose accompanying feature has been finished) will generally be removed once +they're no longer deemed necessary. If a curator can't be reached for comment on a bugfix or review +on a PR'd change for about a month, and hasn't left any indication of when they'll be back, +developers will assume they've left the project, and the mod is orphaned. -Whenever a stable release occurs, mods which no longer qualify for inclusion will be marked 'obsolete'. This doesn't remove them from the repository, but it does prevent it from being used in new worlds (barring additional effort on the part of the player). +Whenever a stable release occurs, mods which no longer qualify for inclusion will be marked +'obsolete'. This doesn't remove them from the repository, but it does prevent it from being used in +new worlds (barring additional effort on the part of the player). ## Why do mods get removed? -While it may be counterintuitive, simply having a mod in the repository increases maintenance burden for the team, even for the people who don't use the mods itself. +While it may be counterintuitive, simply having a mod in the repository increases maintenance burden +for the team, even for the people who don't use the mods itself. -Furthermore, mods which are shipped with the game but are not working correctly for whatever reason reflect poorly on the project on the whole. While it might seem 'easy' to fix a mod, the development team is mostly focused on the core game itself. This is why mod curators are necessary. +Furthermore, mods which are shipped with the game but are not working correctly for whatever reason +reflect poorly on the project on the whole. While it might seem 'easy' to fix a mod, the development +team is mostly focused on the core game itself. This is why mod curators are necessary. ## How can mods be rescued from removal? -If the mod otherwise meets inclusion criteria but lacks a curator (ie. has been declared orphaned), it's as simple as having someone else step forward as the new curator. +If the mod otherwise meets inclusion criteria but lacks a curator (ie. has been declared orphaned), +it's as simple as having someone else step forward as the new curator. -Otherwise, it needs to either be made to meet the criteria, or it simply isn't going to be staying in the CleverRaven repository. +Otherwise, it needs to either be made to meet the criteria, or it simply isn't going to be staying +in the CleverRaven repository. diff --git a/doc/ITEM_SPAWN.md b/doc/ITEM_SPAWN.md index c50db7144fd5..a38cc53e337e 100644 --- a/doc/ITEM_SPAWN.md +++ b/doc/ITEM_SPAWN.md @@ -2,17 +2,23 @@ ## Collection or Distribution -In a Collection each entry is chosen independently from the other entries. Therefore the probability associated with each entry is absolute, in the range of 0...1. In the json files it is implemented as percentage with values from 0 to 100. +In a Collection each entry is chosen independently from the other entries. Therefore the probability +associated with each entry is absolute, in the range of 0...1. In the json files it is implemented +as percentage with values from 0 to 100. -A probability of 0 (or negative) means the entry is never chosen, a probability of 100% means its always chosen. The default is 100, because it's the most useful value. Default 0 would mean the entry can be removed anyway. +A probability of 0 (or negative) means the entry is never chosen, a probability of 100% means its +always chosen. The default is 100, because it's the most useful value. Default 0 would mean the +entry can be removed anyway. -A Distribution is a weighted list like the current system. Exactly one entry is chosen from it. The probability of each entry is relative to the probability of the other entries. A probability of 0 (or negative) means it is never chosen. - -An example: Suppose item A has a probability of 30 and item B has a probability of 20. Then the probabilities of the 4 combinations of A and B are: +A Distribution is a weighted list like the current system. Exactly one entry is chosen from it. The +probability of each entry is relative to the probability of the other entries. A probability of 0 +(or negative) means it is never chosen. +An example: Suppose item A has a probability of 30 and item B has a probability of 20. Then the +probabilities of the 4 combinations of A and B are: | Combination | Collection | Distribution | -| ----------------|------------|------------- | +| --------------- | ---------- | ------------ | | Neither A nor B | 56% | 0% | | Only A | 24% | 60% | | Only B | 14% | 40% | @@ -33,7 +39,8 @@ The format is this: } ``` -`subtype` is optional. It can be `collection` or `distribution`. If unspecified, it defaults to `old`, which denotes that this item group uses the old format (which is technically a distribution). +`subtype` is optional. It can be `collection` or `distribution`. If unspecified, it defaults to +`old`, which denotes that this item group uses the old format (which is technically a distribution). There are [some caveats](#ammo-and-magazines) to watch out for when using `ammo` or `magazine`. @@ -42,32 +49,38 @@ There are [some caveats](#ammo-and-magazines) to watch out for when using `ammo` The `entries` list contains entries, each of which can be one of the following: 1. Item - ```json - { "item": "", ... } - ``` + ```json + { "item": "", ... } + ``` 2. Group - ``` json - { "group": "", ... } - ``` + ```json + { "group": "", ... } + ``` 3. Distribution - ```json - { "distribution": [ - "An array of entries, each of which can match any of these 4 formats" - ] } - ``` + ```json + { + "distribution": [ + "An array of entries, each of which can match any of these 4 formats" + ] + } + ``` 4. Collection - ```json - { "collection": [ - "An array of entries, each of which can match any of these 4 formats" - ] } - ``` + ```json + { + "collection": [ + "An array of entries, each of which can match any of these 4 formats" + ] + } + ``` -The game decides based on the existence of either the `item` or the `group` value if the entry denotes a item or a reference to another item group. +The game decides based on the existence of either the `item` or the `group` value if the entry +denotes a item or a reference to another item group. -Each entry can have more values (shown above as `...`). They allow further properties of the item(s): +Each entry can have more values (shown above as `...`). They allow further properties of the +item(s): ```json "damage": |, @@ -87,11 +100,14 @@ Each entry can have more values (shown above as `...`). They allow further prope "container-group": "", ``` -`contents` is added as contents of the created item. It is not checked if they can be put into the item. This allows water, that contains a book, that contains a steel frame, that contains a corpse. +`contents` is added as contents of the created item. It is not checked if they can be put into the +item. This allows water, that contains a book, that contains a steel frame, that contains a corpse. `count` makes the item spawn repeat to create more items, each time creating a new item. -`charges`: Setting only min, not max will make the game calculate the max charges based on container or ammo/magazine capacity. Setting max too high will decrease it to maximum capacity. Not setting min will set it to 0 when max is set. +`charges`: Setting only min, not max will make the game calculate the max charges based on container +or ammo/magazine capacity. Setting max too high will decrease it to maximum capacity. Not setting +min will set it to 0 when max is set. ```json "damage-min": 0, @@ -100,25 +116,36 @@ Each entry can have more values (shown above as `...`). They allow further prope "charges": [10, 100] ``` -This will create 4 items, they can have different damage levels as the damage value is rolled separately for each of these items. Each item has charges (AKA ammo) in the range of 10 to 100 (inclusive); if the item needs a magazine before it can have charges, that will be taken care of for you. Using an array (which must have 2 entries) for charges/count/damage is equivalent to writing explicit min and max values. In other words `"count": [a,b]` is the same as `"count-min": a, "count-max": b`. +This will create 4 items, they can have different damage levels as the damage value is rolled +separately for each of these items. Each item has charges (AKA ammo) in the range of 10 to 100 +(inclusive); if the item needs a magazine before it can have charges, that will be taken care of for +you. Using an array (which must have 2 entries) for charges/count/damage is equivalent to writing +explicit min and max values. In other words `"count": [a,b]` is the same as +`"count-min": a, "count-max": b`. -The container is checked and the item is put inside the container, and the charges of the item are capped/increased to match the size of the container. +The container is checked and the item is put inside the container, and the charges of the item are +capped/increased to match the size of the container. ### Ammo and Magazines -Here are some ways to make items spawn with/without ammo/magazines (note that `ammo-item` can -be specified for guns and magazines in the entries array to use a non-default ammo type): +Here are some ways to make items spawn with/without ammo/magazines (note that `ammo-item` can be +specified for guns and magazines in the entries array to use a non-default ammo type): -* Specify an ammo/magazine chance (introduced in Section 2) for the entire item group. - `ammo` specifies the percent chance that the entries will spawn fully loaded (if it needs a magazine, it will be added for you). - `magazine` specifies the percent chance that the entries will spawn with a magazine. - Both of these default to 0 if unspecified. +- Specify an ammo/magazine chance (introduced in Section 2) for the entire item group. `ammo` + specifies the percent chance that the entries will spawn fully loaded (if it needs a magazine, it + will be added for you). `magazine` specifies the percent chance that the entries will spawn with a + magazine. Both of these default to 0 if unspecified. - Note that `ammo` and `magazine` only apply to tools, guns, and magazines. Furthermore, they don't apply to tools whose entry explicitly specifies how much ammo (charges) to spawn with, or to tools whose JSON item definition specifies a random amount or a fixed, nonzero amount of initial charges. + Note that `ammo` and `magazine` only apply to tools, guns, and magazines. Furthermore, they don't + apply to tools whose entry explicitly specifies how much ammo (charges) to spawn with, or to tools + whose JSON item definition specifies a random amount or a fixed, nonzero amount of initial + charges. - If any item groups are referenced from your item group, then their ammo/magazine chances are ignored, and yours are used instead. + If any item groups are referenced from your item group, then their ammo/magazine chances are + ignored, and yours are used instead. -* Use `charges`, `charges-min`, or `charges-max` in the entries array. A default magazine will be added for you if needed. +- Use `charges`, `charges-min`, or `charges-max` in the entries array. A default magazine will be + added for you if needed. ## Shortcuts @@ -134,7 +161,8 @@ means the same as: "entries": [ { "item": "" }, { "item": "", "prob": 10 } ] ``` -In other words: a single string denotes an item id, an array (which must contain a string and a number) denotes an item id and a probability. +In other words: a single string denotes an item id, an array (which must contain a string and a +number) denotes an item id and a probability. This is true for groups as well: @@ -142,18 +170,21 @@ This is true for groups as well: "groups": [ "", [ "", 10 ] ] ``` -This format does not support further properties of the created items - the probability is only optional for entries of collections! +This format does not support further properties of the created items - the probability is only +optional for entries of collections! -The content of "entries", "items" and "groups" are all added if those members exist. This will have the item `` appear twice in the item group: +The content of "entries", "items" and "groups" are all added if those members exist. This will have +the item `` appear twice in the item group: ```json { - "items": [ "" ], - "entries": [ { "item": "" } ] + "items": [""], + "entries": [{ "item": "" }] } ``` -Another example. The group "milk" spawns a container (taken from milk_containers) that contains milk (maximal amount that fits into the container, because there is no specific charges value defined). +Another example. The group "milk" spawns a container (taken from milk_containers) that contains milk +(maximal amount that fits into the container, because there is no specific charges value defined). ```json { @@ -177,9 +208,15 @@ Another example. The group "milk" spawns a container (taken from milk_containers ## Inlined item groups -In some places one can define an item group directly instead of giving the id of a group. One can not refer to that group as it has no visible id (it has an unspecific/random id internally). This is most useful when the group is very specific to the place it is used and wont ever appear anywhere else. +In some places one can define an item group directly instead of giving the id of a group. One can +not refer to that group as it has no visible id (it has an unspecific/random id internally). This is +most useful when the group is very specific to the place it is used and wont ever appear anywhere +else. -As an example: monster death drops (`death_drops` entry in the `MONSTER` object, see [JSON_INFO.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_INFO.md)) can do this. If the monster is very specific (e.g. a special robot, a unique endgame monster), the item spawned upon its death won't (in that form) appear in any other group. +As an example: monster death drops (`death_drops` entry in the `MONSTER` object, see +[JSON_INFO.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_INFO.md)) can do +this. If the monster is very specific (e.g. a special robot, a unique endgame monster), the item +spawned upon its death won't (in that form) appear in any other group. Therefore, this snippet: @@ -199,26 +236,30 @@ is equivalent to: ```json { - "death_drops": { - "subtype": "distribution", - "items": [ "a", "b" ] - } + "death_drops": { + "subtype": "distribution", + "items": ["a", "b"] + } } ``` -The inline group is read like any other group and one can use all the properties mentioned above. Its `type` and its `id` members are always ignored. +The inline group is read like any other group and one can use all the properties mentioned above. +Its `type` and its `id` members are always ignored. -Instead of a full JSON object, one can also write a JSON array. The default subtype is used and the array is read like the "entries" array (see above). Each entry of that array must be a JSON object. Example: +Instead of a full JSON object, one can also write a JSON array. The default subtype is used and the +array is read like the "entries" array (see above). Each entry of that array must be a JSON object. +Example: ```json { - "death_drops": [ - { "item": "rag", "damage": 2 }, { "item": "bowling_ball" } - ] + "death_drops": [ + { "item": "rag", "damage": 2 }, + { "item": "bowling_ball" } + ] } ``` ----- +--- ### Notes @@ -227,20 +268,27 @@ Instead of a full JSON object, one can also write a JSON array. The default subt You can test your item groups in the game: 1. Load a game and call the debug menu - > *TIP* (If a key isn't bound to the debug menu or you forgot it, use ESC > 1) + > _TIP_ (If a key isn't bound to the debug menu or you forgot it, use ESC > + > 1) 2. Choose "Test Item Group". 3. Select the item group you want to debug. - The game will then spawn items in that group 100 times and count the spawned items. They'll then be displayed, sorted by their frequency. + The game will then spawn items in that group 100 times and count the spawned items. They'll then + be displayed, sorted by their frequency. - > *TIP*: You can filter anything in the debug menu using / + > _TIP_: You can filter anything in the debug menu using / -You should not add items to the item group `EMPTY_GROUP`. This group can be used when the game requires a group id, but you don't want to spawn any items there. The group will never spawn items. +You should not add items to the item group `EMPTY_GROUP`. This group can be used when the game +requires a group id, but you don't want to spawn any items there. The group will never spawn items. #### SUS -When adding items to item groups, attempt to locate or create **SUS item groups.** SUS item groups are collections that contain a reasonable realistic distribution of items that might spawn in a given piece of storage furniture. SUS stands for "specific use storage." One of the aims of organizing item groups into specific use storage is to promote reusable tables that can be maintained and extended. +When adding items to item groups, attempt to locate or create **SUS item groups.** SUS item groups +are collections that contain a reasonable realistic distribution of items that might spawn in a +given piece of storage furniture. SUS stands for "specific use storage." One of the aims of +organizing item groups into specific use storage is to promote reusable tables that can be +maintained and extended. You can find SUS item groups at /data/json/itemgroups/SUS diff --git a/doc/JSON Mapping Guides/Guide for beginning mapgen.md b/doc/JSON Mapping Guides/Guide for beginning mapgen.md index 209302930c70..a461773c02e0 100644 --- a/doc/JSON Mapping Guides/Guide for beginning mapgen.md +++ b/doc/JSON Mapping Guides/Guide for beginning mapgen.md @@ -1,224 +1,302 @@ ### 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 refer to: [doc/MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md). +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 refer to: +[doc/MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md). First, lets cover some basic concepts and the files you'll add or edit. #### 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. +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: -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 buildings in the game until recent changes allowed special type buildings to spawn inside cities. Examples of specials are: farms, cabins, LMOE, etc. +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 +buildings in the game until recent changes allowed special type buildings to spawn inside cities. +Examples of specials are: farms, cabins, LMOE, etc. -City buildings can be single or multi-tile in size and have their spawns limited to the city boundaries. A building can be both a city building and a special but would require both sets of entries to spawn for both types. Some motels are examples of this (see: 2fmotel_city & 2fmotel). +City buildings can be single or multi-tile in size and have their spawns limited to the city +boundaries. A building can be both a city building and a special but would require both sets of +entries to spawn for both types. Some motels are examples of this (see: 2fmotel_city & 2fmotel). -Important policy: since the roof project, all buildings are now multi-tile across z levels. All new 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. +Important policy: since the roof project, all buildings are now multi-tile across z levels. All new +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: -1. You will add a new mapgen file in: [data/json/mapgen](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/data/json/mapgen) or one of its sub-folders. If you are using an existing foundation shape for the building, you may append it to that building's file. - * This is the blueprint for the building. It can also hold all the building’s data for adding furniture and loot (see palette for an alternative). - -2. You will add entries for each z level you create in the appropriate overmap_terrain file ([data/json/overmap/overmap_terrain](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/data/json/overmap/overmap_terrain)). - * These entries will define what your building looks like in the overmap, its symbol, color, and spawn requirements like adding sidewalks, it will also control flags for some mapgen functions. - -3. You will add an entry into either specials.json or multitile_city_buildings.json depending on if it is a special or a city building. - * For multitile_city_buildings this will link the various z levels &/or multiple OMTs of your building. - * For specials, this will link the various z levels or multiple OMTs of your building, define any needed road/subway/etc. connections, and define its spawning parameters. - -4. Add an entry into regional_settings.json for city buildings. This will allow them to spawn in the world. - -5. Optional but recommended for any large project: adding a new palette file into mapgen_palettes folder (you may use any existing palette too). - * This is a file that can be shared among several maps that holds a portion of the mapgen file data. It is commonly used for defining terrain and furniture. You can also put in loot, vehicle, monster spawns and any other data that normally goes in the `"object"` tag of the mapgen file. - * Please avoid editing existing mapgen palettes because you may affect existing maps using a combination of the palette and the mapgen file. +1. You will add a new mapgen file in: + [data/json/mapgen](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/data/json/mapgen) or + one of its sub-folders. If you are using an existing foundation shape for the building, you may + append it to that building's file. + - This is the blueprint for the building. It can also hold all the building’s data for adding + furniture and loot (see palette for an alternative). + +2. You will add entries for each z level you create in the appropriate overmap_terrain file + ([data/json/overmap/overmap_terrain](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/data/json/overmap/overmap_terrain)). + - These entries will define what your building looks like in the overmap, its symbol, color, and + spawn requirements like adding sidewalks, it will also control flags for some mapgen functions. + +3. You will add an entry into either specials.json or multitile_city_buildings.json depending on if + it is a special or a city building. + - For multitile_city_buildings this will link the various z levels &/or multiple OMTs of your + building. + - For specials, this will link the various z levels or multiple OMTs of your building, define any + needed road/subway/etc. connections, and define its spawning parameters. + +4. Add an entry into regional_settings.json for city buildings. This will allow them to spawn in the + world. + +5. Optional but recommended for any large project: adding a new palette file into mapgen_palettes + folder (you may use any existing palette too). + - This is a file that can be shared among several maps that holds a portion of the mapgen file + data. It is commonly used for defining terrain and furniture. You can also put in loot, + vehicle, monster spawns and any other data that normally goes in the `"object"` tag of the + mapgen file. + - 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: -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 recommend setting up all the needed files when you begin your project. +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 +recommend setting up all the needed files when you begin your project. Before beginning you’ll want to make some decisions: 1. What size will it be overall (how many OMTs?) 2. Where will it spawn? 3. Will I use a palette or put everything in the mapgen file. - * If you use a palette, define as much of it as possible from the outset. + - If you use a palette, define as much of it as possible from the outset. 4. Advanced questions: - * Will I use nested maps? - * Do I want it to connect to the subways or roads? - * 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)? + - Will I use nested maps? + - Do I want it to connect to the subways or roads? + - 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: -This covers the mapgen file map flags and what they do in layman’s terms. You can get more extensive information from [doc/MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md). +This covers the mapgen file map flags and what they do in layman’s terms. You can get more extensive +information from +[doc/MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md). -the mapgen file has some meta data tags and the `"object"` data which defines everything to make the map. +the mapgen file has some meta data tags and the `"object"` data which defines everything to make the +map. ##### The metadata: Sample: + ``` - "type": "mapgen", - "method": "json", - "om_terrain": "s_restaurant_coffee", - "weight": 250, +"type": "mapgen", +"method": "json", +"om_terrain": "s_restaurant_coffee", +"weight": 250, ``` -1. `"type"` will always be mapgen (we'll cover other map types in future tutorials), the `"method"` will always be JSON. This data tells the program how to treat this file. -2. `"om_terrain"`: this is basically your internal name for the map (not the name that shows up on the overmap). It should usually be unique unless you plan on having multiple variants of the same map which **share the same building foundation shape** (note: I mean the actual shape of the building's foundation). +1. `"type"` will always be mapgen (we'll cover other map types in future tutorials), the `"method"` + will always be JSON. This data tells the program how to treat this file. + +2. `"om_terrain"`: this is basically your internal name for the map (not the name that shows up on + the overmap). It should usually be unique unless you plan on having multiple variants of the same + map which **share the same building foundation shape** (note: I mean the actual shape of the + building's foundation). -3. `"weight"`: This entry is the weight of this particular map compared to others **sharing the same om_terrain name**. So, say you have one version of a house then you make an identical house with different spawns (like a fully furnished house and an abandoned version). This weight will 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. +3. `"weight"`: This entry is the weight of this particular map compared to others **sharing the same + om_terrain name**. So, say you have one version of a house then you make an identical house with + different spawns (like a fully furnished house and an abandoned version). This weight will + 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: -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 document we'll be using "explicit symbol" placement for loot spawns, the easiest to use. Everything in the object section can be placed in a mapgen_palette except rows and fill_ter. +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 +document we'll be using "explicit symbol" placement for loot spawns, the easiest to use. Everything +in the object section can be placed in a mapgen_palette except rows and fill_ter. -Sample object segment: everything in the object needs to fall within the object's {} braces or it won't be included. If you misplace the end bracket, you probably won't get a loading error. +Sample object segment: everything in the object needs to fall within the object's {} braces or it +won't be included. If you misplace the end bracket, you probably won't get a loading error. Sample: + ``` - "object": { - "fill_ter": "t_floor", - "rows": [ - "S___________SSTzzzzzzzTS", - "S_____,_____SSzMbMbMbMzS", - "S_____,_____SSSSSSSS/MzS", - "S_____,_____SSSSSSSS/MzS", - "S_____,_____SSzzzSSS/MzS", - "S_____,_____SS||V{{{V||S", - "S_____,_____SS|D <|S", - "SSSSSSSSSSSSSS|r OS", - "SSSSSSSSSSSSSS|r |S", - "SVVVVVVVz./Mzz| #W##|S", - "SVD>>>>Vz./bMzV #ww%|S", - "SV BBB>Vz.b/..{ xwwF|S", - "SV B>Vz.Mb..{ flwl|S", - "SV B>Vz....zV flwU|S", - "SV B>Vzbbbzz|X #wwG|S", - "S|B ^||||||||||^ ||I||S", - "SO6 B|=;|;=|99 r|FwC|S", - "S|B 6|=A|A=|9 r|Fwc|S", - "S| B|+|||+|9 D|!ww|S", - "S|B |Lwl|S", - "SO6 6 6 6 B66B|Lwl|S", - "S|B ^???????^ B66B|Lwl|S", - "S|||||||||||||||||||3||S", - "S4SSSSSSSSSSSSSSSSSSSSSS" - ], - "terrain": { - " ": "t_floor", - "!": "t_linoleum_white", - "#": "t_linoleum_white", - "%": "t_linoleum_white", - "+": "t_door_c", - ",": "t_pavement_y", - ".": "t_grass", - "/": "t_dirt", - "3": [ "t_door_locked", "t_door_locked_alarm" ], - ";": "t_linoleum_white", - "=": "t_linoleum_white", - "A": "t_linoleum_white", - "C": "t_linoleum_white", - "F": "t_linoleum_white", - "G": "t_linoleum_white", - "I": "t_door_locked_interior", - "L": "t_linoleum_white", - "M": "t_dirt", - "O": "t_window", - "S": "t_sidewalk", - "U": "t_linoleum_white", - "V": "t_wall_glass", - "W": "t_fencegate_c", - "_": "t_pavement", - "b": "t_dirt", - "c": "t_linoleum_white", - "f": "t_linoleum_white", - "l": "t_linoleum_white", - "w": "t_linoleum_white", - "x": "t_console_broken", - "z": "t_shrub", - "{": "t_door_glass_c", - "|": "t_wall_b", - "<": "t_stairs_up", - "4": "t_gutter_downspout", - "T": "t_tree_coffee" - }, - "furniture": { - "#": "f_counter", - "%": "f_trashcan", - "/": "f_bluebell", - "6": "f_table", - "9": "f_rack", - ">": "f_counter", - "?": "f_sofa", - "A": "f_sink", - "B": "f_chair", - "C": "f_desk", - "D": "f_trashcan", - "F": "f_fridge", - "G": "f_oven", - "L": "f_locker", - "M": "f_dahlia", - "U": "f_sink", - "X": "f_rack", - "^": "f_indoor_plant", - "b": "f_dandelion", - "f": "f_glass_fridge", - "l": "f_rack", - "r": "f_rack" - }, - "toilets": { ";": { } }, - "items": { - "#": { "item": "coffee_counter", "chance": 10 }, - "6": { "item": "coffee_table", "chance": 35 }, - "9": { "item": "coffee_display_2", "chance": 85, "repeat": [ 1, 8 ] }, - ";": { "item": "coffee_bathroom", "chance": 15 }, - "=": { "item": "coffee_bathroom", "chance": 35 }, - ">": { "item": "coffee_table", "chance": 25 }, - "A": { "item": "coffee_bathroom", "chance": 35 }, - "C": { "item": "office", "chance": 70 }, - "D": { "item": "coffee_trash", "chance": 75 }, - "F": { "item": "coffee_fridge", "chance": 80, "repeat": [ 1, 8 ] }, - "G": { "item": "oven", "chance": 35 }, - "L": { "item": "coffee_locker", "chance": 75 }, - "U": { "item": "coffee_dishes", "chance": 75 }, - "X": { "item": "coffee_newsstand", "chance": 90, "repeat": [ 1, 8 ] }, - "f": { "item": "coffee_freezer", "chance": 85, "repeat": [ 1, 8 ] }, - "l": { "item": "coffee_prep", "chance": 50 }, - "r": { "item": "coffee_condiments", "chance": 80, "repeat": [ 1, 8 ] } - }, - "monsters": { "!": { "monster": "GROUP_COFFEE_SHOP_ZOMBIE", "chance": 1 } }, - "place_monsters": [ { "monster": "GROUP_ZOMBIE", "x": [ 3, 17 ], "y": [ 13, 18 ], "chance": 1 } ], - "vehicles": { "c": { "vehicle": "swivel_chair", "chance": 100, "status": 1 } } - } +"object": { + "fill_ter": "t_floor", + "rows": [ + "S___________SSTzzzzzzzTS", + "S_____,_____SSzMbMbMbMzS", + "S_____,_____SSSSSSSS/MzS", + "S_____,_____SSSSSSSS/MzS", + "S_____,_____SSzzzSSS/MzS", + "S_____,_____SS||V{{{V||S", + "S_____,_____SS|D <|S", + "SSSSSSSSSSSSSS|r OS", + "SSSSSSSSSSSSSS|r |S", + "SVVVVVVVz./Mzz| #W##|S", + "SVD>>>>Vz./bMzV #ww%|S", + "SV BBB>Vz.b/..{ xwwF|S", + "SV B>Vz.Mb..{ flwl|S", + "SV B>Vz....zV flwU|S", + "SV B>Vzbbbzz|X #wwG|S", + "S|B ^||||||||||^ ||I||S", + "SO6 B|=;|;=|99 r|FwC|S", + "S|B 6|=A|A=|9 r|Fwc|S", + "S| B|+|||+|9 D|!ww|S", + "S|B |Lwl|S", + "SO6 6 6 6 B66B|Lwl|S", + "S|B ^???????^ B66B|Lwl|S", + "S|||||||||||||||||||3||S", + "S4SSSSSSSSSSSSSSSSSSSSSS" + ], + "terrain": { + " ": "t_floor", + "!": "t_linoleum_white", + "#": "t_linoleum_white", + "%": "t_linoleum_white", + "+": "t_door_c", + ",": "t_pavement_y", + ".": "t_grass", + "/": "t_dirt", + "3": [ "t_door_locked", "t_door_locked_alarm" ], + ";": "t_linoleum_white", + "=": "t_linoleum_white", + "A": "t_linoleum_white", + "C": "t_linoleum_white", + "F": "t_linoleum_white", + "G": "t_linoleum_white", + "I": "t_door_locked_interior", + "L": "t_linoleum_white", + "M": "t_dirt", + "O": "t_window", + "S": "t_sidewalk", + "U": "t_linoleum_white", + "V": "t_wall_glass", + "W": "t_fencegate_c", + "_": "t_pavement", + "b": "t_dirt", + "c": "t_linoleum_white", + "f": "t_linoleum_white", + "l": "t_linoleum_white", + "w": "t_linoleum_white", + "x": "t_console_broken", + "z": "t_shrub", + "{": "t_door_glass_c", + "|": "t_wall_b", + "<": "t_stairs_up", + "4": "t_gutter_downspout", + "T": "t_tree_coffee" + }, + "furniture": { + "#": "f_counter", + "%": "f_trashcan", + "/": "f_bluebell", + "6": "f_table", + "9": "f_rack", + ">": "f_counter", + "?": "f_sofa", + "A": "f_sink", + "B": "f_chair", + "C": "f_desk", + "D": "f_trashcan", + "F": "f_fridge", + "G": "f_oven", + "L": "f_locker", + "M": "f_dahlia", + "U": "f_sink", + "X": "f_rack", + "^": "f_indoor_plant", + "b": "f_dandelion", + "f": "f_glass_fridge", + "l": "f_rack", + "r": "f_rack" + }, + "toilets": { ";": { } }, + "items": { + "#": { "item": "coffee_counter", "chance": 10 }, + "6": { "item": "coffee_table", "chance": 35 }, + "9": { "item": "coffee_display_2", "chance": 85, "repeat": [ 1, 8 ] }, + ";": { "item": "coffee_bathroom", "chance": 15 }, + "=": { "item": "coffee_bathroom", "chance": 35 }, + ">": { "item": "coffee_table", "chance": 25 }, + "A": { "item": "coffee_bathroom", "chance": 35 }, + "C": { "item": "office", "chance": 70 }, + "D": { "item": "coffee_trash", "chance": 75 }, + "F": { "item": "coffee_fridge", "chance": 80, "repeat": [ 1, 8 ] }, + "G": { "item": "oven", "chance": 35 }, + "L": { "item": "coffee_locker", "chance": 75 }, + "U": { "item": "coffee_dishes", "chance": 75 }, + "X": { "item": "coffee_newsstand", "chance": 90, "repeat": [ 1, 8 ] }, + "f": { "item": "coffee_freezer", "chance": 85, "repeat": [ 1, 8 ] }, + "l": { "item": "coffee_prep", "chance": 50 }, + "r": { "item": "coffee_condiments", "chance": 80, "repeat": [ 1, 8 ] } + }, + "monsters": { "!": { "monster": "GROUP_COFFEE_SHOP_ZOMBIE", "chance": 1 } }, + "place_monsters": [ { "monster": "GROUP_ZOMBIE", "x": [ 3, 17 ], "y": [ 13, 18 ], "chance": 1 } ], + "vehicles": { "c": { "vehicle": "swivel_chair", "chance": 100, "status": 1 } } +} ``` -1. The `"fill_ter"`: this tag defines the default terrain/flooring for use under furniture and for undefined symbols in your rows. Generally, pick the terrain that has the most furniture associated with it. +1. The `"fill_ter"`: this tag defines the default terrain/flooring for use under furniture and for + undefined symbols in your rows. Generally, pick the terrain that has the most furniture + associated with it. -2. The `"rows"`: this is the actual blueprint for your building. A standard OMT tile (overmap tile) is 24x24 tiles. Rows begin their x,y coordinates at 0,0 which is the upper left corner of your map. - * tip: if you cross stitch or are familiar with cross stitch patterns, this should all look very familiar. You have the map and the "legend" areas. +2. The `"rows"`: this is the actual blueprint for your building. A standard OMT tile (overmap tile) + is 24x24 tiles. Rows begin their x,y coordinates at 0,0 which is the upper left corner of your + map. + - tip: if you cross stitch or are familiar with cross stitch patterns, this should all look very + familiar. You have the map and the "legend" areas. -3. `"terrain"`: this defines what all those letters in the rows mean when they are terrains. A symbol can return a single terrain, or, it can offer a chance to spawn from a selection of terrains. Here are some quick examples: +3. `"terrain"`: this defines what all those letters in the rows mean when they are terrains. A + symbol can return a single terrain, or, it can offer a chance to spawn from a selection of + terrains. Here are some quick examples: `"*": "t_door_c",`: this will make every * in the rows a closed wooden door. -`"*": [ [ "t_door_locked_peep", 2 ], "t_door_locked_alarm", [ "t_door_locked", 10 ], "t_door_c" ],`: this array will randomly choose from a selection of doors. Some are weighted to have a higher chance to spawn then others. Locked doors will be most common, then peephole doors. Finally closed & locked/alarmed have the same basic weight and will spawn the least. - -*Note: in my example, the fill_ter is for floor. So if you have furniture that you want to spawn with a different floor, you must use that same symbol that you've given the furniture and also define it as a terrain for your new flooring. In the above example, several furniture symbols are using white linoleum for their flooring. If you don't do this step, your furniture will end up having the wrong flooring which will be especially noticeable if you smash it. I often do a final map check where I go around in game and smash furniture to check their terrains before submitting my maps. This can be quite cathartic.* - -4. `"furniture"` tag: Like terrain, this is a list of the furniture ID's and their map symbols. It can handle the same sort of arrays as terrain. - -5. `"toilets"` and other specially defined furniture: you'll run into some specially defined common furniture which allows for some easier placement. In our sample map the entry: `"toilets": { ";": { } },` defines the symbol entry and will also auto-place water in your toilets. There are a few other specialty furniture entries. - -The other most common one is: `"vendingmachines": { "D": { "item_group": "vending_drink" }, "V": { "item_group": "vending_food" } }` this assigns two symbols for vending machines and makes one for food & one for drinks. *note: you 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: [doc/ITEM_SPAWN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/ITEM_SPAWN.md). - -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 in another tutorial. +`"*": [ [ "t_door_locked_peep", 2 ], "t_door_locked_alarm", [ "t_door_locked", 10 ], "t_door_c" ],`: +this array will randomly choose from a selection of doors. Some are weighted to have a higher chance +to spawn then others. Locked doors will be most common, then peephole doors. Finally closed & +locked/alarmed have the same basic weight and will spawn the least. + +_Note: in my example, the fill_ter is for floor. So if you have furniture that you want to spawn +with a different floor, you must use that same symbol that you've given the furniture and also +define it as a terrain for your new flooring. In the above example, several furniture symbols are +using white linoleum for their flooring. If you don't do this step, your furniture will end up +having the wrong flooring which will be especially noticeable if you smash it. I often do a final +map check where I go around in game and smash furniture to check their terrains before submitting my +maps. This can be quite cathartic._ + +4. `"furniture"` tag: Like terrain, this is a list of the furniture ID's and their map symbols. It + can handle the same sort of arrays as terrain. + +5. `"toilets"` and other specially defined furniture: you'll run into some specially defined common + furniture which allows for some easier placement. In our sample map the entry: + `"toilets": { ";": { } },` defines the symbol entry and will also auto-place water in your + toilets. There are a few other specialty furniture entries. + +The other most common one is: +`"vendingmachines": { "D": { "item_group": "vending_drink" }, "V": { "item_group": "vending_food" } }` +this assigns two symbols for vending machines and makes one for food & one for drinks. _note: you +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: + [doc/ITEM_SPAWN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/ITEM_SPAWN.md). + +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 +in another tutorial. For now lets break this one apart: + ``` "items": { "a": { "item": "stash_wood", "chance": 30, "repeat": [ 2, 5 ] }, @@ -229,11 +307,20 @@ For now lets break this one apart: } ``` -"a" in this case is a fireplace as defined in its map. So, in the fireplace I want to add the stash_wood item_group. By defining the group under "a", every fireplace in my map will get this group. This is particularly powerful for common item_groups like in houses where every fridge is going to get the same item_group. The chance is its spawn chance and repeat means that it will repeat the roll for that chance 2-5 times, so this fireplace can be extra stocked or have a little bit or nothing if it fails its chance rolls. +"a" in this case is a fireplace as defined in its map. So, in the fireplace I want to add the +stash_wood item_group. By defining the group under "a", every fireplace in my map will get this +group. This is particularly powerful for common item_groups like in houses where every fridge is +going to get the same item_group. The chance is its spawn chance and repeat means that it will +repeat the roll for that chance 2-5 times, so this fireplace can be extra stocked or have a little +bit or nothing if it fails its chance rolls. + +the "d" entry is a dresser. I wanted the dressers to pull from two possible item groups, one a man's +selection and the other women’s. So, there is an array [ ... ] which encompasses all possible +item_groups for this symbol. -the "d" entry is a dresser. I wanted the dressers to pull from two possible item groups, one a man's selection and the other women’s. So, there is an array [ ... ] which encompasses all possible item_groups for this symbol. +You can add as many item_groups to the array as you'd like. This is one of my racks in the generic +house palette: -You can add as many item_groups to the array as you'd like. This is one of my racks in the generic house palette: ``` "q": [ { "item": "tools_home", "chance": 40 }, @@ -244,23 +331,37 @@ You can add as many item_groups to the array as you'd like. This is one of my r ], ``` -*Note: When using explicit symbol placements, remember your group has a chance to spawn in every furniture using that symbol, so it can end up being quite generous. If you want two bookcases with different item spawns, give each bookcase its own symbol, or, use an alternate item spawn format, like the one using x,y coordinates for placement.* +_Note: When using explicit symbol placements, remember your group has a chance to spawn in every +furniture using that symbol, so it can end up being quite generous. If you want two bookcases with +different item spawns, give each bookcase its own symbol, or, use an alternate item spawn format, +like the one using x,y coordinates for placement._ + +7. Monster spawns: our example has two types of monster spawns listed. -7. Monster spawns: our example has two types of monster spawns listed. ``` "monsters": { "!": { "monster": "GROUP_COFFEE_SHOP_ZOMBIE", "chance": 1 } }, "place_monsters": [ { "monster": "GROUP_ZOMBIE", "x": [ 3, 17 ], "y": [ 13, 18 ], "chance": 1 } ], ``` -The first entry is using that explicit symbol placement technique. The end entry is using a range x,y coordinates to place monsters. *Note: We are moving away from putting monsters in the mapgen file in favor of overmap_terrain entries, so only use this if you want a specific monster group to spawn for specific reasons. See overmap_terrain section for more information.* +The first entry is using that explicit symbol placement technique. The end entry is using a range +x,y coordinates to place monsters. _Note: We are moving away from putting monsters in the mapgen +file in favor of overmap_terrain entries, so only use this if you want a specific monster group to +spawn for specific reasons. See overmap_terrain section for more information._ 8. Vehicle spawns: + ``` "vehicles": { "c": { "vehicle": "swivel_chair", "chance": 100, "status": 1 } } ``` + Our vehicle happens to be a swivel chair using explicit symbol placement. -This next example uses vehicle_groups and x,y placement. It also includes rotation and status. The rotation is which direction the vehicle will spawn on the map, and that status is its overall condition. Fuel is pretty self explanatory. Always test your vehcile spawns in game, they can be rather picky in their placement and the rotation doesn't really match what you'd expect the numbers to mean. The 0,0 point of vehicles can vary so you'll have to experiment to get the spawns in the right spots, especially in tight spaces. +This next example uses vehicle_groups and x,y placement. It also includes rotation and status. The +rotation is which direction the vehicle will spawn on the map, and that status is its overall +condition. Fuel is pretty self explanatory. Always test your vehcile spawns in game, they can be +rather picky in their placement and the rotation doesn't really match what you'd expect the numbers +to mean. The 0,0 point of vehicles can vary so you'll have to experiment to get the spawns in the +right spots, especially in tight spaces. ``` "place_vehicles": [ @@ -273,17 +374,21 @@ This next example uses vehicle_groups and x,y placement. It also includes rotat { "chance": 75, "fuel": 0, "rotation": 270, "status": 1, "vehicle": "junkyard_vehicles", "x": 28, "y": 18 }, { "chance": 75, "fuel": 0, "rotation": 270, "status": 1, "vehicle": "junkyard_vehicles", "x": 35, "y": 18 } ] - ``` +``` -9. Liquids in furniture: this entry is for a standing tank. I've defined the tank in the furniture entry as "g". +9. Liquids in furniture: this entry is for a standing tank. I've defined the tank in the furniture + entry as "g". `"liquids": { "g": { "liquid": "water_clean", "amount": [ 0, 100 ] } },` This places clean water in the tank, and a range of amount to spawn. -10. There are other specialty placement techniques that you'll pick up as you look at more maps. One of my favorites is for the new planters: +10. There are other specialty placement techniques that you'll pick up as you look at more maps. One + of my favorites is for the new planters: -Since the planter is a "sealed item" you define what's going into that container. This example places seeds (ready to harvest) in the planters. Note the first one will place a seedling, the others are harvest ready. I've given each planter type an explicit symbol for quicker placement. +Since the planter is a "sealed item" you define what's going into that container. This example +places seeds (ready to harvest) in the planters. Note the first one will place a seedling, the +others are harvest ready. I've given each planter type an explicit symbol for quicker placement. ``` "sealed_item": { @@ -297,111 +402,139 @@ Since the planter is a "sealed item" you define what's going into that container "8": { "item": { "item": "soybean_seed" }, "furniture": "f_planter_harvest" }, "9": { "item": { "item": "seed_zucchini" }, "furniture": "f_planter_harvest" } } - ``` +``` -11. Best practices: - * If you are making a new house please use this palette: "standard_domestic_palette". The loots are already assigned and it covers a wide range of domestic furniture. This will keep your house in sync with all the other houses for loot spawns. - * All buildings should also get roof entries. - * While entry placement for json doesn't really matter, try to keep your mapgen files ordered like the majority existing maps. Be kind to future contributors. - Add meta data at the top of the file. - Object entry comes second. Within the object entry it is generally: palette, set_points, terrain, furniture, random special entries like toilets, item spawns, vehicle spawns, monster spawns. - * All buildings should at least get one "t_gutter_downspout" for roof access. Players would love at least 2. - if you're adding gutters to a multi-z level building, don't forget the intermediate floors. You'll need to stagger the downspouts to players can climb up (like ladders). - * If you put things on your roof that would be difficult to get up there, make sure to provide better roof access via ladders and stairs. - * For your basic grass cover outside please use: `"t_region_groundcover_urban",` to maintain consistency across map boundaries. Here are my standard flora entries for grass, shrubs & trees: +11. Best practices: + +- If you are making a new house please use this palette: "standard_domestic_palette". The loots are + already assigned and it covers a wide range of domestic furniture. This will keep your house in + sync with all the other houses for loot spawns. +- All buildings should also get roof entries. +- While entry placement for json doesn't really matter, try to keep your mapgen files ordered like + the majority existing maps. Be kind to future contributors. Add meta data at the top of the file. + Object entry comes second. Within the object entry it is generally: palette, set_points, terrain, + furniture, random special entries like toilets, item spawns, vehicle spawns, monster spawns. +- All buildings should at least get one "t_gutter_downspout" for roof access. Players would love at + least 2. if you're adding gutters to a multi-z level building, don't forget the intermediate + floors. You'll need to stagger the downspouts to players can climb up (like ladders). +- If you put things on your roof that would be difficult to get up there, make sure to provide + better roof access via ladders and stairs. +- For your basic grass cover outside please use: `"t_region_groundcover_urban",` to maintain + consistency across map boundaries. Here are my standard flora entries for grass, shrubs & trees: ``` - ".": "t_region_groundcover_urban", - "A": [ "t_region_shrub", "t_region_shrub_fruit", "t_region_shrub_decorative" ], - "Z": [ [ "t_region_tree_fruit", 2 ], [ "t_region_tree_nut", 2 ], "t_region_tree_shade" ], +".": "t_region_groundcover_urban", +"A": [ "t_region_shrub", "t_region_shrub_fruit", "t_region_shrub_decorative" ], +"Z": [ [ "t_region_tree_fruit", 2 ], [ "t_region_tree_nut", 2 ], "t_region_tree_shade" ], ``` finally for flowers (which are furniture): + ``` "p": "f_region_flower" ``` #### 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 other floors that share the same building shape/foundation. +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 +other floors that share the same building shape/foundation. -So, this is super easy compared to the building we just went over. It has all the same basic components. I recommend you start by using the rows from your ground floor map and converting it to the `"roof_palette"` symbol set. Basically your just going to trace the outline in gutters, add a t_gutter_drop next to your t_gutter_spout below and toss some infrastructure up there. I used nests extensively in commercial building roofs and we'll cover that in advanced mapgen. +So, this is super easy compared to the building we just went over. It has all the same basic +components. I recommend you start by using the rows from your ground floor map and converting it to +the `"roof_palette"` symbol set. Basically your just going to trace the outline in gutters, add a +t_gutter_drop next to your t_gutter_spout below and toss some infrastructure up there. I used nests +extensively in commercial building roofs and we'll cover that in advanced mapgen. sample roof: + ``` - { - "type": "mapgen", - "method": "json", - "om_terrain": "house_01_roof", - "object": { - "fill_ter": "t_shingle_flat_roof", - "rows": [ - " ", - " ", - " ", - " |222222222222222223 ", - " |.................3 ", - " |.................3 ", - " |.............N...3 ", - " 5.................3 ", - " |.................3 ", - " |.................3 ", - " |........&........3 ", - " |.................3 ", - " |......=..........3 ", - " |.................3 ", - " |----------------53 ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " - ], - "palettes": [ "roof_palette" ], - "terrain": { ".": "t_shingle_flat_roof" } - } +{ + "type": "mapgen", + "method": "json", + "om_terrain": "house_01_roof", + "object": { + "fill_ter": "t_shingle_flat_roof", + "rows": [ + " ", + " ", + " ", + " |222222222222222223 ", + " |.................3 ", + " |.................3 ", + " |.............N...3 ", + " 5.................3 ", + " |.................3 ", + " |.................3 ", + " |........&........3 ", + " |.................3 ", + " |......=..........3 ", + " |.................3 ", + " |----------------53 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ], + "palettes": [ "roof_palette" ], + "terrain": { ".": "t_shingle_flat_roof" } } - ``` +} +``` - 1. I always just append `_roof` to the buildings ID. - 2. See how the palette takes the place of all that data from our earlier example. So clean and easy. - 3. There is no `"weight"` entry because this will only spawn with its building (once linked). - 4. My palette uses "t_flat_roof" as its default roof. For houses, I wanted shingles. So, I added the "t_shingle_flat_roof" in this mapgen which will override the palettes entry for `".": "t_flat_roof"`. (more on this in advanced mapgen). +1. I always just append `_roof` to the buildings ID. +2. See how the palette takes the place of all that data from our earlier example. So clean and easy. +3. There is no `"weight"` entry because this will only spawn with its building (once linked). +4. My palette uses "t_flat_roof" as its default roof. For houses, I wanted shingles. So, I added the + "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: [doc/JSON Mapping Guides/JSON_ROOF_MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON%20Mapping%20Guides/JSON_ROOF_MAPGEN.md). +I have a separate roof document at: +[doc/JSON Mapping Guides/JSON_ROOF_MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON%20Mapping%20Guides/JSON_ROOF_MAPGEN.md). #### Linking various mapgen maps using multitile_city_buildings.json - This file is found at: [data/json/overmap/multitile_city_buildings.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/overmap/multitile_city_buildings.json). +This file is found at: +[data/json/overmap/multitile_city_buildings.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/overmap/multitile_city_buildings.json). - *Remember this file is for city buildings only, not specials* +_Remember this file is for city buildings only, not specials_ - A standard entry: - ``` - { - "type": "city_building", - "id": "house_dogs", - "locations": [ "land" ], - "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "house_dogs_north" }, - { "point": [ 0, 0, 1 ], "overmap": "house_dogs_roof_north" }, - { "point": [ 0, 0, -1 ], "overmap": "basement" } - ] - }, - ``` +A standard entry: + +``` +{ + "type": "city_building", + "id": "house_dogs", + "locations": [ "land" ], + "overmaps": [ + { "point": [ 0, 0, 0 ], "overmap": "house_dogs_north" }, + { "point": [ 0, 0, 1 ], "overmap": "house_dogs_roof_north" }, + { "point": [ 0, 0, -1 ], "overmap": "basement" } + ] +}, +``` - 1. The `"type"` won't change. It should always be "city_building". - 2. `"id"`: This ID is often the same as your mapgen ID but it doesn't have to be the same. We could use something more generic like "house". This ID will be used in regional settings for spawns, so keep in mind how many buildings are using the ID. I prefer distinct ID's because it makes debug spawning much, much easier. - 3. `"locations"`: defines where this building can be place by overmap terrain type. Land is the default. - 4. `"overmaps"`: this is the bit where you define how the maps fit together, so lets break it up: - `{ "point": [ 0, 0, 0 ], "overmap": "house_dogs_north" },` - point: its point in relation to the other mapgen files for your building. The coordinates are [ x, y, z ]. In this example, x,y are 0 because we only have one map per z level. Zero for y means this is the ground level. Note the roof above is at 1 and the basement is -1. - 5. appending `_north` to the ID's: - * If your building rotates you need this compass point so the floors can match up correctly. This is the generic basement mapgen group and thus doesn't get `_north` (this will change as we add dedicated stairs to our houses). +1. The `"type"` won't change. It should always be "city_building". +2. `"id"`: This ID is often the same as your mapgen ID but it doesn't have to be the same. We could + use something more generic like "house". This ID will be used in regional settings for spawns, so + keep in mind how many buildings are using the ID. I prefer distinct ID's because it makes debug + spawning much, much easier. +3. `"locations"`: defines where this building can be place by overmap terrain type. Land is the + default. +4. `"overmaps"`: this is the bit where you define how the maps fit together, so lets break it up: + `{ "point": [ 0, 0, 0 ], "overmap": "house_dogs_north" },` point: its point in relation to the + other mapgen files for your building. The coordinates are [ x, y, z ]. In this example, x,y are 0 + because we only have one map per z level. Zero for y means this is the ground level. Note the + roof above is at 1 and the basement is -1. +5. appending `_north` to the ID's: + - If your building rotates you need this compass point so the floors can match up correctly. This + 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 @@ -409,16 +542,20 @@ I have a separate roof document at: [doc/JSON Mapping Guides/JSON_ROOF_MAPGEN.md 1. For city buildings and houses you'll scroll down to the `"city":` flag. 2. Find your appropriate subtag, `"houses"` or `"shops"` usually. -3. Add your ID from the multitile_city_buildings entry. This can also accept the mapgen ID and not complain which is why the are often the same name. +3. Add your ID from the multitile_city_buildings entry. This can also accept the mapgen ID and not + complain which is why the are often the same name. 4. Choose a good weight for your building. #### Linking and spawning specials: -Put the entry in: [data/json/overmap/overmap_special/specials.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/overmap/overmap_special/specials.json). +Put the entry in: +[data/json/overmap/overmap_special/specials.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/overmap/overmap_special/specials.json). -This entry does the job of both the regional_map_settings and multitile_city_buildings plus other fun overmap stuff. +This entry does the job of both the regional_map_settings and multitile_city_buildings plus other +fun overmap stuff. Example: + ``` { "type": "overmap_special", @@ -444,146 +581,176 @@ Example: "occurrences": [ 0, 1 ], "flags": [ "CLASSIC" ] } - ``` - - 1. `"type"`: is overmap_special. - 2. `"id"` is your buildings ID for the overmap. It also displays on the overmap in game. - 3. `"overmaps"` this works the same way as it does in the city building entries. Note that the pump station is bigger then 1 OMT on the ground, so the y coordinate changes as well. - 4. `"connections"`: this places road, sewer, subway connections for your map. - 5. `"locations"`: valid OMT types this building can be placed on. - 6. `"city_distance"`, `"city_sizes"` both are parameters for where this spawns in relation to cities. - 7. `"occurrences": [ 0, 1 ],`: Ok so occurrences can mean two things depending on if it uses the "UNIQUE" flag or not. When the flag is absent, this simply translates to how many times this special can spawn PER overmap. So 0 to 1 in this case. - If you use the UNIQUE flag, this becomes a 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: [doc/JSON_FLAGS.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_FLAGS.md). +``` -Read: [doc/OVERMAP.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/OVERMAP.md) for more details. +1. `"type"`: is overmap_special. +2. `"id"` is your buildings ID for the overmap. It also displays on the overmap in game. +3. `"overmaps"` this works the same way as it does in the city building entries. Note that the pump + station is bigger then 1 OMT on the ground, so the y coordinate changes as well. +4. `"connections"`: this places road, sewer, subway connections for your map. +5. `"locations"`: valid OMT types this building can be placed on. +6. `"city_distance"`, `"city_sizes"` both are parameters for where this spawns in relation to + cities. +7. `"occurrences": [ 0, 1 ],`: Ok so occurrences can mean two things depending on if it uses the + "UNIQUE" flag or not. When the flag is absent, this simply translates to how many times this + special can spawn PER overmap. So 0 to 1 in this case. If you use the UNIQUE flag, this becomes a + 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: + [doc/JSON_FLAGS.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/JSON_FLAGS.md). + +Read: [doc/OVERMAP.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/OVERMAP.md) for +more details. #### Overmap_terrain entries: -Choose a file for your building type at: [data/json/overmap/overmap_terrain](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/data/json/overmap/overmap_terrain). +Choose a file for your building type at: +[data/json/overmap/overmap_terrain](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/data/json/overmap/overmap_terrain). -This set of entries defines how your building will look on the overmap. It supports copy-from. +This set of entries defines how your building will look on the overmap. It supports copy-from. Example: + +``` +{ + "type": "overmap_terrain", + "id": "s_music", + "copy-from": "generic_city_building", + "name": "music store", + "sym": "m", + "color": "brown", + "mondensity": 2, + "extend": { "flags": [ "SOURCE_LUXURY" ] } +}, +{ + "type": "overmap_terrain", + "id": "s_music_roof", + "copy-from": "generic_city_building", + "name": "music store roof", + "sym": "m", + "color": "brown" +} ``` - { - "type": "overmap_terrain", - "id": "s_music", - "copy-from": "generic_city_building", - "name": "music store", - "sym": "m", - "color": "brown", - "mondensity": 2, - "extend": { "flags": [ "SOURCE_LUXURY" ] } - }, - { - "type": "overmap_terrain", - "id": "s_music_roof", - "copy-from": "generic_city_building", - "name": "music store roof", - "sym": "m", - "color": "brown" - } - ``` You need one entry per mapgen ID: + 1. `"type"` will always be overmap_terrain. 2. `"id"` will be the same ID you used in your mapgen file. 3. `"copy-from"` this will copy any data from another entry, excepting what you define here. 4. `"name"` how the name displays on the overmap. 5. `"sym"` the symbol displayed on the overmap. If left out, the carrots will be used `v<>^` 6. `"color"` color for overmap symbol. -7. `"mondesntiy"` sets the default monster density for this overmap tile. You'll use this for general zombie spawns and reserve the mapgen monster entries for special spanwns for that location (e.g. a pet store's pets). -8. `"extend"` many of these flags will be used by NPCs in the future for their AI, try to add flags appropriate for your location. Others further define the mapgen, like having sidewalks generate. +7. `"mondesntiy"` sets the default monster density for this overmap tile. You'll use this for + general zombie spawns and reserve the mapgen monster entries for special spanwns for that + location (e.g. a pet store's pets). +8. `"extend"` many of these flags will be used by NPCs in the future for their AI, try to add flags + appropriate for your location. Others further define the mapgen, like having sidewalks generate. -For further information see: [Overmap Terrain section of doc/OVERMAP.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/OVERMAP.md#overmap-terrain). +For further information see: +[Overmap Terrain section of doc/OVERMAP.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/OVERMAP.md#overmap-terrain). #### 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 data to related maps and to maintain symbol consistency. +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 +data to related maps and to maintain symbol consistency. -Entries that are added to the mapgen file's object will over ride the same symbol used in the palette. In this way, you can use a palette and make select alterations to each mapgen as needed. This is especially useful for multiple ground terrains like carpets, concrete, etc. +Entries that are added to the mapgen file's object will over ride the same symbol used in the +palette. In this way, you can use a palette and make select alterations to each mapgen as needed. +This is especially useful for multiple ground terrains like carpets, concrete, etc. -Terrain works very well when you substitute it via the mapgen file. I've had less success overriding furniture but need to test it more to clarify when it works as intended. I have recently noticed that if your palette symbol uses an array of values, the mapgen entry can't override it. +Terrain works very well when you substitute it via the mapgen file. I've had less success overriding +furniture but need to test it more to clarify when it works as intended. I have recently noticed +that if your palette symbol uses an array of values, the mapgen entry can't override it. -Example: -Entry for the mapgen file object: `"palettes": [ "roof_palette" ],` +Example: Entry for the mapgen file object: `"palettes": [ "roof_palette" ],` The palette metadata: + ``` - "type": "palette", - "id": "roof_palette", +"type": "palette", +"id": "roof_palette", ``` Everything else will look like a series of object entries, for example the roof_palette: ``` - { - "type": "palette", - "id": "roof_palette", - "terrain": { - ".": "t_flat_roof", - " ": "t_open_air", - "o": "t_glass_roof", - "_": "t_floor", - "2": "t_gutter_north", - "-": "t_gutter_south", - "3": "t_gutter_east", - "4": "t_gutter_downspout", - "|": "t_gutter_west", - "5": "t_gutter_drop", - "#": "t_grate", - "&": "t_null", - ":": "t_null", - "X": "t_null", - "=": "t_null", - "A": "t_null", - "b": "t_null", - "c": "t_null", - "t": "t_null", - "r": "t_null", - "L": "t_null", - "C": "t_null", - "Y": "t_null", - "y": "t_null" - }, - "furniture": { - "&": "f_roof_turbine_vent", - "N": "f_TV_antenna", - ":": "f_cellphone_booster", - "X": "f_small_satelitte_dish", - "~": "f_chimney", - "=": "f_vent_pipe", - "A": "f_air_conditioner", - "b": "f_bench", - "c": "f_counter", - "t": "f_table", - "r": "f_rack", - "L": "f_locker", - "C": [ "f_crate_c", "f_cardboard_box" ], - "Y": "f_stool", - "s": "f_sofa", - "S": "f_sink", - "e": "f_oven", - "F": "f_fridge", - "y": [ "f_indoor_plant_y", "f_indoor_plant" ] - }, - "toilets": { "T": { } } - } - ``` +{ + "type": "palette", + "id": "roof_palette", + "terrain": { + ".": "t_flat_roof", + " ": "t_open_air", + "o": "t_glass_roof", + "_": "t_floor", + "2": "t_gutter_north", + "-": "t_gutter_south", + "3": "t_gutter_east", + "4": "t_gutter_downspout", + "|": "t_gutter_west", + "5": "t_gutter_drop", + "#": "t_grate", + "&": "t_null", + ":": "t_null", + "X": "t_null", + "=": "t_null", + "A": "t_null", + "b": "t_null", + "c": "t_null", + "t": "t_null", + "r": "t_null", + "L": "t_null", + "C": "t_null", + "Y": "t_null", + "y": "t_null" + }, + "furniture": { + "&": "f_roof_turbine_vent", + "N": "f_TV_antenna", + ":": "f_cellphone_booster", + "X": "f_small_satelitte_dish", + "~": "f_chimney", + "=": "f_vent_pipe", + "A": "f_air_conditioner", + "b": "f_bench", + "c": "f_counter", + "t": "f_table", + "r": "f_rack", + "L": "f_locker", + "C": [ "f_crate_c", "f_cardboard_box" ], + "Y": "f_stool", + "s": "f_sofa", + "S": "f_sink", + "e": "f_oven", + "F": "f_fridge", + "y": [ "f_indoor_plant_y", "f_indoor_plant" ] + }, + "toilets": { "T": { } } +} +``` -If you want to look at more complex palettes, the standard_domestic_palette in [data/json/mapgen_palettes/house_general_palette.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/mapgen_palettes/house_general_palette.json) is a good look at a palette designed to work across all CDDA houses. It includes the loot spawns and accounts for most furniture that will be used in a house. I also left a list of symbols open to be used in the mapgen file for specific location needs. +If you want to look at more complex palettes, the standard_domestic_palette in +[data/json/mapgen_palettes/house_general_palette.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/mapgen_palettes/house_general_palette.json) +is a good look at a palette designed to work across all CDDA houses. It includes the loot spawns and +accounts for most furniture that will be used in a house. I also left a list of symbols open to be +used in the mapgen file for specific location needs. -Finally, the series of house_w palettes at [data/json/mapgen_palettes/house_w_palette.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/mapgen_palettes/house_w_palette.json) are designed to work together for houses using nested mapgen. There is a palette devoted to the foundation, another for the nests, and finally another one I've designed for domestic outdoor nested chunks. +Finally, the series of house_w palettes at +[data/json/mapgen_palettes/house_w_palette.json](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/data/json/mapgen_palettes/house_w_palette.json) +are designed to work together for houses using nested mapgen. There is a palette devoted to the +foundation, another for the nests, and finally another one I've designed for domestic outdoor nested +chunks. #### 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. +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. Not covered in this document: - * Nested maps and their placement. - * NPC spawns. - * Advanced terrain tricks for complex floor options. - * traps, terrain and you. - * update_mapgen (NPC and player triggered map updates). - * faction camp expansion maps. - * field emitting furniture. + +- Nested maps and their placement. +- NPC spawns. +- Advanced terrain tricks for complex floor options. +- traps, terrain and you. +- update_mapgen (NPC and player triggered map updates). +- faction camp expansion maps. +- field emitting furniture. diff --git a/doc/JSON Mapping Guides/JSON_ROOF_MAPGEN.md b/doc/JSON Mapping Guides/JSON_ROOF_MAPGEN.md index 883e0fd25530..efd6d87f04fb 100644 --- a/doc/JSON Mapping Guides/JSON_ROOF_MAPGEN.md +++ b/doc/JSON Mapping Guides/JSON_ROOF_MAPGEN.md @@ -1,6 +1,7 @@ # Adding Json Roof Guide -Adding json roofs to a building involves using a few more files to link the roof and building together during mapgen. +Adding json roofs to a building involves using a few more files to link the roof and building +together during mapgen. Files that will be edited: @@ -14,140 +15,155 @@ Files that will be edited: ## Making the Roof Map -Refer to [MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md) for creating the map if you are new to map creation. +Refer to [MAPGEN.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/MAPGEN.md) for +creating the map if you are new to map creation. -Open the file that contains the map for the building `data/json/mapgen/[name of building].json` -Add a new entry for the roof. You can copy the building entry since you want the same foundation footprint for the roof. +Open the file that contains the map for the building `data/json/mapgen/[name of building].json` Add +a new entry for the roof. You can copy the building entry since you want the same foundation +footprint for the roof. -Give the roof a unique om_terrain ID. Below is an example of the main floor and roof om_terrain IDs +Give the roof a unique om_terrain ID. Below is an example of the main floor and roof om_terrain IDs -````json +```json "om_terrain": [ "abstorefront" ], "om_terrain": [ "abstorefront_roof" ], -```` +``` -Note: If you are adding a roof to an existing building that shares a common om_terrain ID with other maps, you will need to change the om_terrain ID for the existing floor to be unique. +Note: If you are adding a roof to an existing building that shares a common om_terrain ID with other +maps, you will need to change the om_terrain ID for the existing floor to be unique. -Keep the outline of the walls from the original floor, -Add `t_open_air` outside the building and a `t_flat_roof` over the building's footprint. -There are a few flat roof terrains to choose from in terrain.json. +Keep the outline of the walls from the original floor, Add `t_open_air` outside the building and a +`t_flat_roof` over the building's footprint. There are a few flat roof terrains to choose from in +terrain.json. -There are a number of terrains and furniture structures for roofs including gutters, chimneys, and roof turbine vents. -Browse json/terrain.json and furniture.json for ideas. Consider roof access, you can use ladders, stairs and gutters. Some furniture is also climbable. +There are a number of terrains and furniture structures for roofs including gutters, chimneys, and +roof turbine vents. Browse json/terrain.json and furniture.json for ideas. Consider roof access, you +can use ladders, stairs and gutters. Some furniture is also climbable. -There is a set of optional nested map chunks at `data/json/mapgen/nested_chunks_roof.json` if you'd like to incorporate them. Add any new nested chunks for roofs here as well. +There is a set of optional nested map chunks at `data/json/mapgen/nested_chunks_roof.json` if you'd +like to incorporate them. Add any new nested chunks for roofs here as well. Sample roof entry: -````json - { - "type": "mapgen", - "method": "json", - "om_terrain": "abstorefront_roof", - "weight": 200, - "object": { - "fill_ter": "t_flat_roof", - "rows": [ - " ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |....................3 ", - " |......&.............3 ", - " |....................3 ", - " |....................3 ", - " |-----------------5--3 ", - " ", - " ", - " ", - " ", - " ", - " ", - " ", - " " - ], - "terrain": { - ".": "t_flat_roof", - " ": "t_open_air", - "|": "t_gutter_west", - "-": "t_gutter_south", - "3": "t_gutter_east", - "5": "t_gutter_drop" - }, - "furniture": { "&": "f_roof_turbine_vent" }, - "place_items": [ { "item": "roof_trash", "x": [ 2, 21 ], "y": [ 3, 14 ], "chance": 50, "repeat": [ 1, 3 ] } ], - "place_nested": [ - { - "chunks": [ - [ "null", 50 ], - [ "roof_4x4_party", 15 ], - [ "roof_4x4_holdout", 5 ], - [ "roof_4x4_utility", 40 ], - [ "roof_5x5_coop", 5 ] - ], - "x": [ 3, 15 ], - "y": [ 3, 7 ] - } - ] - } + +```json +{ + "type": "mapgen", + "method": "json", + "om_terrain": "abstorefront_roof", + "weight": 200, + "object": { + "fill_ter": "t_flat_roof", + "rows": [ + " ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |....................3 ", + " |......&.............3 ", + " |....................3 ", + " |....................3 ", + " |-----------------5--3 ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " " + ], + "terrain": { + ".": "t_flat_roof", + " ": "t_open_air", + "|": "t_gutter_west", + "-": "t_gutter_south", + "3": "t_gutter_east", + "5": "t_gutter_drop" + }, + "furniture": { "&": "f_roof_turbine_vent" }, + "place_items": [ + { "item": "roof_trash", "x": [2, 21], "y": [3, 14], "chance": 50, "repeat": [1, 3] } + ], + "place_nested": [ + { + "chunks": [ + ["null", 50], + ["roof_4x4_party", 15], + ["roof_4x4_holdout", 5], + ["roof_4x4_utility", 40], + ["roof_5x5_coop", 5] + ], + "x": [3, 15], + "y": [3, 7] + } + ] + } } -```` +``` ## Linking the main floor and the roof -Navigate to `json/overmap/multitile_city_buildings.json` or `json/overmap/multitile_buildings_terrain.json` for buildings taking up more then one overmap tile per z level (schools, mansions). -Add an entry for the main floor. The `point` coordinates define to the x, y, z positions of the building. The 1 places the roof one z level above the ground floor. + +Navigate to `json/overmap/multitile_city_buildings.json` or +`json/overmap/multitile_buildings_terrain.json` for buildings taking up more then one overmap tile +per z level (schools, mansions). Add an entry for the main floor. The `point` coordinates define to +the x, y, z positions of the building. The 1 places the roof one z level above the ground floor. Append north for rotating buildings to orient the z levels. -````json - { - "type": "city_building", - "id": "abstorefront", - "locations": [ "land" ], - "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "abstorefront_north" }, - { "point": [ 0, 0, 1 ], "overmap": "abstorefront_roof_north" } - ] - } -```` +```json +{ + "type": "city_building", + "id": "abstorefront", + "locations": ["land"], + "overmaps": [ + { "point": [0, 0, 0], "overmap": "abstorefront_north" }, + { "point": [0, 0, 1], "overmap": "abstorefront_roof_north" } + ] +} +``` + ## Overmap Specials -Overmap specials are handled a little differently. They use `json/overmap/specials.json` for both linking z levels and overmap spawning. A special won't need an entry in `data/json/regional_map_settings.json` +Overmap specials are handled a little differently. They use `json/overmap/specials.json` for both +linking z levels and overmap spawning. A special won't need an entry in +`data/json/regional_map_settings.json` Overmap special example: -````json - { - "type" : "overmap_special", - "id" : "Evac Shelter", - "overmaps" : [ - { "point":[0,0,0], "overmap": "shelter"}, - { "point":[0,0,-1], "overmap": "shelter_under"}, - { "point":[0,0,1], "overmap": "shelter_roof"} - ], - "connections" : [ - { "point" : [0,-1,0], "terrain" : "road" } - ], - "locations" : [ "wilderness" ], - "city_distance" : [5, 10], - "city_sizes" : [4, 12], - "occurrences" : [1, 3], - "rotate" : false, - "flags" : [ "CLASSIC" ] - } -```` + +```json +{ + "type": "overmap_special", + "id": "Evac Shelter", + "overmaps": [ + { "point": [0, 0, 0], "overmap": "shelter" }, + { "point": [0, 0, -1], "overmap": "shelter_under" }, + { "point": [0, 0, 1], "overmap": "shelter_roof" } + ], + "connections": [ + { "point": [0, -1, 0], "terrain": "road" } + ], + "locations": ["wilderness"], + "city_distance": [5, 10], + "city_sizes": [4, 12], + "occurrences": [1, 3], + "rotate": false, + "flags": ["CLASSIC"] +} +``` + ## Adding the overmap_terrain entry -Navigate to `data/json/overmap_terrain.json` -Every z level gets an entry that defines how it appears on the overmap. -The name field will determine what is displayed in the in-game overmap. -The entries should share the same color and symbol. +Navigate to `data/json/overmap_terrain.json` Every z level gets an entry that defines how it appears +on the overmap. The name field will determine what is displayed in the in-game overmap. The entries +should share the same color and symbol. -````json +```json { "type": "overmap_terrain", "id": "abandonedwarehouse", @@ -164,16 +180,20 @@ The entries should share the same color and symbol. "sym": 119, "color": "brown" } -```` +``` + ## Adding to regional_map_settings + Navigate to `data/json/regional_map_settings.json` -This determines the spawn frequency and location of non-special buildings. -Find the appropriate category for your building and add either the overmap_special ID or the city_building ID and include a spawn weight. +This determines the spawn frequency and location of non-special buildings. Find the appropriate +category for your building and add either the overmap_special ID or the city_building ID and include +a spawn weight. -````json +```json ""abandonedwarehouse": 200, -```` +``` + When testing you can increase the spawn rate if you want to survey your work using natural spawns. Finally, always [lint](http://dev.narc.ro/cataclysm/format.html) your additions before submitting. diff --git a/doc/JSON_FLAGS.md b/doc/JSON_FLAGS.md index 2ed65f71b5d2..719955c97bbc 100644 --- a/doc/JSON_FLAGS.md +++ b/doc/JSON_FLAGS.md @@ -47,7 +47,7 @@ - [Sizes](#sizes) - [Special attacks](#special-attacks) - [Mutations](#mutations) - - [Flags](#flags-7) + - [Flags](#flags-7) - [Categories](#categories-1) - [Overmap](#overmap) - [Overmap connections](#overmap-connections) @@ -73,431 +73,489 @@ - [Vehicle parts requiring other vehicle parts](#vehicle-parts-requiring-other-vehicle-parts) - [Fuel types](#fuel-types) - ## Notes -- Some flags (items, effects, vehicle parts) have to be defined in `flags.json` or `vp_flags.json` (with type: `json_flag`) to work correctly. -- Many of the flags intended for one category or item type, can be used in other categories or item types. Experiment to see where else flags can be used. +- Some flags (items, effects, vehicle parts) have to be defined in `flags.json` or `vp_flags.json` + (with type: `json_flag`) to work correctly. +- Many of the flags intended for one category or item type, can be used in other categories or item + types. Experiment to see where else flags can be used. - Offensive and defensive flags can be used on any item type that can be wielded. - ## Inheritance -When an item is crafted, it can inherit flags from the components that were used to craft it. This requires that the flag to be inherited has the `"craft_inherit": true` entry. If you don't want a particular item to inherit flags when crafted, specify the member delete_flags, which is an array of strings. Flags specified there will be removed from the resultant item upon crafting. This will override flag inheritance, but will not delete flags that are part of the item type itself. - +When an item is crafted, it can inherit flags from the components that were used to craft it. This +requires that the flag to be inherited has the `"craft_inherit": true` entry. If you don't want a +particular item to inherit flags when crafted, specify the member delete_flags, which is an array of +strings. Flags specified there will be removed from the resultant item upon crafting. This will +override flag inheritance, but will not delete flags that are part of the item type itself. ## TODO -- Descriptions for `Special attacks` under `Monsters` could stand to be more descriptive of exactly what the attack does. -- `Ammo effects` under `Ammo` need more descriptive details, and some need to be double-checked for accuracy. - +- Descriptions for `Special attacks` under `Monsters` could stand to be more descriptive of exactly + what the attack does. +- `Ammo effects` under `Ammo` need more descriptive details, and some need to be double-checked for + accuracy. ## Ammo ### Ammo type -These are handled through `ammo_types.json`. You can tag a weapon with these to have it chamber existing ammo, or make your own ammo there. The first column in this list is the tag's "id", the internal identifier DDA uses to track the tag, and the second is a brief description of the ammo tagged. Use the id to search for ammo listings, as ids are constant throughout DDA's code. Happy chambering! :-) - -- ```120mm``` 120mm HEAT -- ```12mm``` 12mm -- ```20x66mm``` 20x66mm Shot (and relatives) -- ```223``` .223 Remington (and 5.56 NATO) -- ```22``` .22LR (and relatives) -- ```3006``` 30.06 -- ```300``` .300 WinMag -- ```308``` .308 Winchester (and relatives) -- ```32``` .32 ACP -- ```36paper``` .36 cap & ball -- ```38``` .38 Special -- ```40``` 10mm -- ```40mm``` 40mm Grenade -- ```44``` .44 Magnum -- ```44paper``` .44 cap & ball -- ```454``` .454 Casull -- ```45``` .45 ACP (and relatives) -- ```46``` 46mm -- ```500``` .500 Magnum -- ```50``` .50 BMG -- ```57``` 57mm -- ```5x50``` 5x50 Dart -- ```66mm``` 66mm HEAT -- ```700nx``` .700 Nitro Express -- ```762R``` 7.62x54mm -- ```762``` 7.62x39mm -- ```762x25``` 7.62x25mm -- ```84x246mm``` 84x246mm HE -- ```8x40mm``` 8mm Caseless -- ```9mm``` 9x19mm Luger (and relatives) -- ```9x18``` 9x18mm -- ```BB``` BB -- ```RPG-7``` RPG-7 -- ```UPS``` UPS charges -- ```ammo_flintlock``` Flintlock ammo -- ```ampoule``` Ampoule -- ```arrow``` Arrow -- ```battery``` Battery -- ```blunderbuss``` Blunderbuss -- ```bolt``` Bolt -- ```charcoal``` Charcoal -- ```components``` Components -- ```dart``` Dart -- ```diesel``` Diesel -- ```fish_bait``` Fish bait -- ```fishspear``` Speargun spear -- ```fusion``` Laser Pack -- ```gasoline``` Gasoline -- ```homebrew_rocket``` homebrew rocket -- ```lamp_oil``` Lamp oil -- ```laser_capacitor``` Charge -- ```m235``` M235 TPA (66mm Incendiary Rocket) -- ```metal_rail``` Rebar Rail -- ```money``` Cents -- ```muscle``` Muscle -- ```nail``` Nail -- ```pebble``` Pebble -- ```plasma``` Plasma -- ```plutonium``` Plutonium Cell -- ```rebreather_filter``` Rebreather filter -- ```shot``` Shotshell -- ```signal_flare``` Signal Flare -- ```tape``` Duct tape -- ```thread``` Thread -- ```thrown``` Thrown -- ```unfinished_char``` Semi-charred fuel -- ```water``` Water +These are handled through `ammo_types.json`. You can tag a weapon with these to have it chamber +existing ammo, or make your own ammo there. The first column in this list is the tag's "id", the +internal identifier DDA uses to track the tag, and the second is a brief description of the ammo +tagged. Use the id to search for ammo listings, as ids are constant throughout DDA's code. Happy +chambering! :-) + +- `120mm` 120mm HEAT +- `12mm` 12mm +- `20x66mm` 20x66mm Shot (and relatives) +- `223` .223 Remington (and 5.56 NATO) +- `22` .22LR (and relatives) +- `3006` 30.06 +- `300` .300 WinMag +- `308` .308 Winchester (and relatives) +- `32` .32 ACP +- `36paper` .36 cap & ball +- `38` .38 Special +- `40` 10mm +- `40mm` 40mm Grenade +- `44` .44 Magnum +- `44paper` .44 cap & ball +- `454` .454 Casull +- `45` .45 ACP (and relatives) +- `46` 46mm +- `500` .500 Magnum +- `50` .50 BMG +- `57` 57mm +- `5x50` 5x50 Dart +- `66mm` 66mm HEAT +- `700nx` .700 Nitro Express +- `762R` 7.62x54mm +- `762` 7.62x39mm +- `762x25` 7.62x25mm +- `84x246mm` 84x246mm HE +- `8x40mm` 8mm Caseless +- `9mm` 9x19mm Luger (and relatives) +- `9x18` 9x18mm +- `BB` BB +- `RPG-7` RPG-7 +- `UPS` UPS charges +- `ammo_flintlock` Flintlock ammo +- `ampoule` Ampoule +- `arrow` Arrow +- `battery` Battery +- `blunderbuss` Blunderbuss +- `bolt` Bolt +- `charcoal` Charcoal +- `components` Components +- `dart` Dart +- `diesel` Diesel +- `fish_bait` Fish bait +- `fishspear` Speargun spear +- `fusion` Laser Pack +- `gasoline` Gasoline +- `homebrew_rocket` homebrew rocket +- `lamp_oil` Lamp oil +- `laser_capacitor` Charge +- `m235` M235 TPA (66mm Incendiary Rocket) +- `metal_rail` Rebar Rail +- `money` Cents +- `muscle` Muscle +- `nail` Nail +- `pebble` Pebble +- `plasma` Plasma +- `plutonium` Plutonium Cell +- `rebreather_filter` Rebreather filter +- `shot` Shotshell +- `signal_flare` Signal Flare +- `tape` Duct tape +- `thread` Thread +- `thrown` Thrown +- `unfinished_char` Semi-charred fuel +- `water` Water ### Effects -- ```ACIDBOMB``` Leaves a pool of acid on detonation. -- ```BEANBAG``` Stuns the target. -- ```BLACKPOWDER``` May clog up the gun with blackpowder fouling, which will also cause rust. -- ```BLINDS_EYES``` Blinds the target if it hits the head (ranged projectiles can't actually hit the eyes at the moment). -- ```BOUNCE``` Inflicts target with `bounced` effect and rebounds to a nearby target without this effect. -- ```COOKOFF``` Explodes when lit on fire. -- ```CUSTOM_EXPLOSION``` Explosion as specified in ```"explosion"``` field of used ammo. See `JSON_INFO.md`. -- ```DRAW_AS_LINE``` Doesn't go through regular bullet animation, instead draws a line and the bullet on its end for one frame. -- ```EXPLOSIVE_BIG``` Large explosion without any shrapnel. -- ```EXPLOSIVE_HUGE``` Huge explosion without any shrapnel. -- ```EXPLOSIVE``` Explodes without any shrapnel. -- ```FLAME``` Very small explosion that lights fires. -- ```FLARE``` Lights the target on fire. -- ```FLASHBANG``` Blinds and deafens nearby targets. -- ```FRAG``` Small explosion that spreads shrapnel. -- ```INCENDIARY``` Lights target on fire. -- ```LARGE_BEANBAG``` Heavily stuns the target. -- ```LASER``` Creates a trail of laser (the field type) -- ```LIGHTNING``` Creates a trail of lightning. -- ```MININUKE_MOD``` Small thermo-nuclear detonation that leaves behind radioactive fallout. -- ```MUZZLE_SMOKE``` Generate a small cloud of smoke at the source. -- ```NAPALM``` Explosion that spreads fire. -- ```NEVER_MISFIRES``` Firing ammo without this flag may trigger a misfiring, this is independent of the weapon flags. -- ```NOGIB``` Prevents overkill damage on the target (target won't explode into gibs, see also the monster flag NO_GIBS). -- ```NO_PENETRATE_OBSTACLES``` Prevents a projectile from going through a tile with obstacles, such as chainlink fences or dressers. -- ```TANGLE``` When this projectile hits a target, it has a chance to tangle them up and immobilise them. -- ```NO_EMBED``` When an item would be spawned from the projectile, it will always be spawned on the ground rather than in monster's inventory. Implied for active thrown items. Doesn't do anything on projectiles that do not drop items. -- ```NO_ITEM_DAMAGE``` Will not damage items on the map even when it otherwise would try to. -- ```PLASMA``` Creates a trail of superheated plasma. -- ```RECOVER_[X]``` Has a (X-1/X) chance to create a single charge of the used ammo at the point of impact. -- ```RECYCLED``` (For handmade ammo) causes the gun to misfire sometimes, this independent of the weapon flags. -- ```SHOT``` Multiple smaller pellets; less effective against armor but increases chance to hit and no point-blank penalty -- ```SMOKE_BIG``` Generates a large cloud of smoke at the target. -- ```SMOKE``` Generates a cloud of smoke at the target. -- ```STREAM_BIG``` Leaves a trail of intense fire fields. -- ```STREAM``` Leaves a trail of fire fields. -- ```TRAIL``` Creates a trail of smoke. -- ```WIDE``` Prevents `HARDTOSHOOT` monster flag from having any effect. Implied by ```SHOT``` or liquid ammo. - +- `ACIDBOMB` Leaves a pool of acid on detonation. +- `BEANBAG` Stuns the target. +- `BLACKPOWDER` May clog up the gun with blackpowder fouling, which will also cause rust. +- `BLINDS_EYES` Blinds the target if it hits the head (ranged projectiles can't actually hit the + eyes at the moment). +- `BOUNCE` Inflicts target with `bounced` effect and rebounds to a nearby target without this + effect. +- `COOKOFF` Explodes when lit on fire. +- `CUSTOM_EXPLOSION` Explosion as specified in `"explosion"` field of used ammo. See `JSON_INFO.md`. +- `DRAW_AS_LINE` Doesn't go through regular bullet animation, instead draws a line and the bullet on + its end for one frame. +- `EXPLOSIVE_BIG` Large explosion without any shrapnel. +- `EXPLOSIVE_HUGE` Huge explosion without any shrapnel. +- `EXPLOSIVE` Explodes without any shrapnel. +- `FLAME` Very small explosion that lights fires. +- `FLARE` Lights the target on fire. +- `FLASHBANG` Blinds and deafens nearby targets. +- `FRAG` Small explosion that spreads shrapnel. +- `INCENDIARY` Lights target on fire. +- `LARGE_BEANBAG` Heavily stuns the target. +- `LASER` Creates a trail of laser (the field type) +- `LIGHTNING` Creates a trail of lightning. +- `MININUKE_MOD` Small thermo-nuclear detonation that leaves behind radioactive fallout. +- `MUZZLE_SMOKE` Generate a small cloud of smoke at the source. +- `NAPALM` Explosion that spreads fire. +- `NEVER_MISFIRES` Firing ammo without this flag may trigger a misfiring, this is independent of the + weapon flags. +- `NOGIB` Prevents overkill damage on the target (target won't explode into gibs, see also the + monster flag NO_GIBS). +- `NO_PENETRATE_OBSTACLES` Prevents a projectile from going through a tile with obstacles, such as + chainlink fences or dressers. +- `TANGLE` When this projectile hits a target, it has a chance to tangle them up and immobilise + them. +- `NO_EMBED` When an item would be spawned from the projectile, it will always be spawned on the + ground rather than in monster's inventory. Implied for active thrown items. Doesn't do anything on + projectiles that do not drop items. +- `NO_ITEM_DAMAGE` Will not damage items on the map even when it otherwise would try to. +- `PLASMA` Creates a trail of superheated plasma. +- `RECOVER_[X]` Has a (X-1/X) chance to create a single charge of the used ammo at the point of + impact. +- `RECYCLED` (For handmade ammo) causes the gun to misfire sometimes, this independent of the weapon + flags. +- `SHOT` Multiple smaller pellets; less effective against armor but increases chance to hit and no + point-blank penalty +- `SMOKE_BIG` Generates a large cloud of smoke at the target. +- `SMOKE` Generates a cloud of smoke at the target. +- `STREAM_BIG` Leaves a trail of intense fire fields. +- `STREAM` Leaves a trail of fire fields. +- `TRAIL` Creates a trail of smoke. +- `WIDE` Prevents `HARDTOSHOOT` monster flag from having any effect. Implied by `SHOT` or liquid + ammo. ## Armor ### Covers -- ```ARMS``` ... same ```ARM_L``` and ```ARM_R``` -- ```ARM_L``` -- ```ARM_R``` -- ```EYES``` -- ```FEET``` ... same ```FOOT_L``` and ```FOOT_R``` -- ```FOOT_L``` -- ```FOOT_R``` -- ```HANDS``` ... same ```HAND_L``` and ```HAND_R``` -- ```HAND_L``` -- ```HAND_R``` -- ```HEAD``` -- ```LEGS``` ... same ```LEG_L``` and ```LEG_R``` -- ```LEG_L``` -- ```LEG_R``` -- ```MOUTH``` -- ```TORSO``` +- `ARMS` ... same `ARM_L` and `ARM_R` +- `ARM_L` +- `ARM_R` +- `EYES` +- `FEET` ... same `FOOT_L` and `FOOT_R` +- `FOOT_L` +- `FOOT_R` +- `HANDS` ... same `HAND_L` and `HAND_R` +- `HAND_L` +- `HAND_R` +- `HEAD` +- `LEGS` ... same `LEG_L` and `LEG_R` +- `LEG_L` +- `LEG_R` +- `MOUTH` +- `TORSO` ### Flags -Some armor flags, such as `WATCH` and `ALARMCLOCK` are compatible with other item types. Experiment to find which flags work elsewhere. - -- ```ACTIVE_CLOAKING``` While active, drains UPS to provide invisibility. -- ```ALARMCLOCK``` Has an alarm-clock feature. -- ```ALLOWS_NATURAL_ATTACKS``` Doesn't prevent any natural attacks or similar benefits from mutations, fingertip razors, etc., like most items covering the relevant body part would. -- ```AURA``` This item goes in the outer aura layer, intended for metaphysical effects. -- ```BAROMETER``` This gear is equipped with an accurate barometer (which is used to measure atmospheric pressure). -- ```BELTED``` Layer for backpacks and things worn over outerwear. -- ```BLIND``` Blinds the wearer while worn, and provides nominal protection v. flashbang flashes. -- ```BLOCK_WHILE_WORN``` Allows worn armor or shields to be used for blocking attacks. See also the `Techniques` section. -- ```BULLET_IMMNUE``` Wearing an item with this flag makes you immune to bullet damage -- ```CLIMATE_CONTROL``` This piece of clothing has climate control of some sort, keeping you warmer or cooler depending on ambient and bodily temperature. -- ```COLLAR``` This piece of clothing has a wide collar that can keep your mouth warm. -- ```DEAF``` Makes the player deaf. -- ```ELECTRIC_IMMUNE``` This gear completely protects you from electric discharges. -- ```FANCY``` Wearing this clothing gives a morale bonus if the player has the `Stylish` trait. -- ```FIX_FARSIGHT``` This gear corrects farsightedness. -- ```FIX_NEARSIGHT``` This gear corrects nearsightedness. -- ```FLOTATION``` Prevents the player from drowning in deep water. Also prevents diving underwater. -- ```FRAGILE``` This gear is less resistant to damage than normal. -- ```HELMET_COMPAT``` Items that are not SKINTIGHT or OVERSIZE but can be worn with a helmet. -- ```HOOD``` Allow this clothing to conditionally cover the head, for additional warmth or water protection., if the player's head isn't encumbered -- ```HYGROMETER``` This gear is equipped with an accurate hygrometer (which is used to measure humidity). -- ```NO_TAKEOFF``` Item with that flag can't be taken off. -- ```NO_QUICKDRAW``` Don't offer to draw items from this holster when the fire key is pressed whilst the players hands are empty -- ```ONLY_ONE``` You can wear only one. -- ```OUTER``` Outer garment layer. -- ```OVERSIZE``` Can always be worn no matter encumbrance/mutations/bionics/etc., but prevents any other clothing being worn over this. -- ```PARTIAL_DEAF``` Reduces the volume of sounds to a safe level. -- ```PERSONAL``` This item goes in the personal aura layer, intended for metaphysical effects. -- ```POCKETS``` Increases warmth for hands if the player's hands are cold and the player is wielding nothing. -- ```POWERARMOR_EXO``` Marks the item as the main exoskeleton for power armor. -- ```POWERARMOR_EXTERNAL``` Marks the item as external pieces that cover body parts the exoskeleton doesn't. -- ```POWERARMOR_MOD``` Marks the item as a power armour mod that is worn onto an exoskeleton/external piece. -- ```POWERARMOR_COMPATIBLE``` Makes item compatible with power armor despite other parameters causing failure. -- ```PSYSHIELD_PARTIAL``` 25% chance to protect against fear_paralyze monster attack when worn. -- ```RAD_PROOF``` This piece of clothing completely protects you from radiation. -- ```RAD_RESIST``` This piece of clothing partially protects you from radiation. -- ```RAINPROOF``` Prevents the covered body-part(s) from getting wet in the rain. -- ```REQUIRES_BALANCE``` Gear that requires a certain balance to be steady with. If the player is hit while wearing, they have a chance to be downed. -- ```RESTRICT_HANDS``` Prevents the player from wielding a weapon two-handed, forcing one-handed use if the weapon permits it. -- ```ROLLER_ONE``` A less stable and slower version of ROLLER_QUAD, still allows the player to move faster than walking speed. -- ```ROLLER_QUAD```The medium choice between ROLLER_INLINE and ROLLER_ONE, while it is more stable, and moves faster, it also has a harsher non-flat terrain penalty then ROLLER_ONE. -- ```ROLLER_INLINE``` Faster, but less stable overall, the penalty for non-flat terrain is even harsher. -- ```SEMITANGIBLE``` Prevents the item from participating in the encumbrance system when worn. -- ```COMPACT``` Prevents the item from participating in the layering encumbrance system when worn. -- ```SKINTIGHT``` Undergarment layer. -- ```SLOWS_MOVEMENT``` This piece of clothing multiplies move cost by 1.1. -- ```SLOWS_THIRST``` This piece of clothing multiplies the rate at which the player grows thirsty by 0.70. -- ```STURDY``` This clothing is a lot more resistant to damage than normal. -- ```SUN_GLASSES``` Prevents glaring when in sunlight. -- ```SUPER_FANCY``` Gives an additional moral bonus over `FANCY` if the player has the `Stylish` trait. -- ```SWIM_GOGGLES``` Allows you to see much further under water. -- ```THERMOMETER``` This gear is equipped with an accurate thermometer (which is used to measure temperature). -- ```VARSIZE``` Can be made to fit via tailoring. -- ```WAIST``` Layer for belts other things worn on the waist. -- ```WATCH``` Acts as a watch and allows the player to see actual time. -- ```WATERPROOF``` Prevents the covered body-part(s) from getting wet in any circumstance. -- ```WATER_FRIENDLY``` Prevents the item from making the body part count as unfriendly to water and thus causing negative morale from being wet. - +Some armor flags, such as `WATCH` and `ALARMCLOCK` are compatible with other item types. Experiment +to find which flags work elsewhere. + +- `ACTIVE_CLOAKING` While active, drains UPS to provide invisibility. +- `ALARMCLOCK` Has an alarm-clock feature. +- `ALLOWS_NATURAL_ATTACKS` Doesn't prevent any natural attacks or similar benefits from mutations, + fingertip razors, etc., like most items covering the relevant body part would. +- `AURA` This item goes in the outer aura layer, intended for metaphysical effects. +- `BAROMETER` This gear is equipped with an accurate barometer (which is used to measure atmospheric + pressure). +- `BELTED` Layer for backpacks and things worn over outerwear. +- `BLIND` Blinds the wearer while worn, and provides nominal protection v. flashbang flashes. +- `BLOCK_WHILE_WORN` Allows worn armor or shields to be used for blocking attacks. See also the + `Techniques` section. +- `BULLET_IMMNUE` Wearing an item with this flag makes you immune to bullet damage +- `CLIMATE_CONTROL` This piece of clothing has climate control of some sort, keeping you warmer or + cooler depending on ambient and bodily temperature. +- `COLLAR` This piece of clothing has a wide collar that can keep your mouth warm. +- `DEAF` Makes the player deaf. +- `ELECTRIC_IMMUNE` This gear completely protects you from electric discharges. +- `FANCY` Wearing this clothing gives a morale bonus if the player has the `Stylish` trait. +- `FIX_FARSIGHT` This gear corrects farsightedness. +- `FIX_NEARSIGHT` This gear corrects nearsightedness. +- `FLOTATION` Prevents the player from drowning in deep water. Also prevents diving underwater. +- `FRAGILE` This gear is less resistant to damage than normal. +- `HELMET_COMPAT` Items that are not SKINTIGHT or OVERSIZE but can be worn with a helmet. +- `HOOD` Allow this clothing to conditionally cover the head, for additional warmth or water + protection., if the player's head isn't encumbered +- `HYGROMETER` This gear is equipped with an accurate hygrometer (which is used to measure + humidity). +- `NO_TAKEOFF` Item with that flag can't be taken off. +- `NO_QUICKDRAW` Don't offer to draw items from this holster when the fire key is pressed whilst the + players hands are empty +- `ONLY_ONE` You can wear only one. +- `OUTER` Outer garment layer. +- `OVERSIZE` Can always be worn no matter encumbrance/mutations/bionics/etc., but prevents any other + clothing being worn over this. +- `PARTIAL_DEAF` Reduces the volume of sounds to a safe level. +- `PERSONAL` This item goes in the personal aura layer, intended for metaphysical effects. +- `POCKETS` Increases warmth for hands if the player's hands are cold and the player is wielding + nothing. +- `POWERARMOR_EXO` Marks the item as the main exoskeleton for power armor. +- `POWERARMOR_EXTERNAL` Marks the item as external pieces that cover body parts the exoskeleton + doesn't. +- `POWERARMOR_MOD` Marks the item as a power armour mod that is worn onto an exoskeleton/external + piece. +- `POWERARMOR_COMPATIBLE` Makes item compatible with power armor despite other parameters causing + failure. +- `PSYSHIELD_PARTIAL` 25% chance to protect against fear_paralyze monster attack when worn. +- `RAD_PROOF` This piece of clothing completely protects you from radiation. +- `RAD_RESIST` This piece of clothing partially protects you from radiation. +- `RAINPROOF` Prevents the covered body-part(s) from getting wet in the rain. +- `REQUIRES_BALANCE` Gear that requires a certain balance to be steady with. If the player is hit + while wearing, they have a chance to be downed. +- `RESTRICT_HANDS` Prevents the player from wielding a weapon two-handed, forcing one-handed use if + the weapon permits it. +- `ROLLER_ONE` A less stable and slower version of ROLLER_QUAD, still allows the player to move + faster than walking speed. +- `ROLLER_QUAD`The medium choice between ROLLER_INLINE and ROLLER_ONE, while it is more stable, and + moves faster, it also has a harsher non-flat terrain penalty then ROLLER_ONE. +- `ROLLER_INLINE` Faster, but less stable overall, the penalty for non-flat terrain is even harsher. +- `SEMITANGIBLE` Prevents the item from participating in the encumbrance system when worn. +- `COMPACT` Prevents the item from participating in the layering encumbrance system when worn. +- `SKINTIGHT` Undergarment layer. +- `SLOWS_MOVEMENT` This piece of clothing multiplies move cost by 1.1. +- `SLOWS_THIRST` This piece of clothing multiplies the rate at which the player grows thirsty by + 0.70. +- `STURDY` This clothing is a lot more resistant to damage than normal. +- `SUN_GLASSES` Prevents glaring when in sunlight. +- `SUPER_FANCY` Gives an additional moral bonus over `FANCY` if the player has the `Stylish` trait. +- `SWIM_GOGGLES` Allows you to see much further under water. +- `THERMOMETER` This gear is equipped with an accurate thermometer (which is used to measure + temperature). +- `VARSIZE` Can be made to fit via tailoring. +- `WAIST` Layer for belts other things worn on the waist. +- `WATCH` Acts as a watch and allows the player to see actual time. +- `WATERPROOF` Prevents the covered body-part(s) from getting wet in any circumstance. +- `WATER_FRIENDLY` Prevents the item from making the body part count as unfriendly to water and thus + causing negative morale from being wet. ## Bionics -- ```BIONIC_ARMOR_INTERFACE``` This bionic can provide power to powered armor. -- ```BIONIC_FAULTY``` This bionic is a "faulty" bionic. -- ```BIONIC_GUN``` This bionic is a gun bionic and activating it will fire it. Prevents all other activation effects. -- ```BIONIC_NPC_USABLE``` The NPC AI knows how to use this CBM and it can be installed on an NPC. -- ```BIONIC_POWER_SOURCE``` This bionic is a power source bionic. -- ```BIONIC_SLEEP_FRIENDLY``` This bionic won't prompt the user to turn it off if they try to sleep while it's active. -- ```BIONIC_TOGGLED``` This bionic only has a function when activated, else it causes it's effect every turn. -- ```BIONIC_WEAPON``` This bionic is a weapon bionic and activating it will create (or destroy) bionic's fake_item in user's hands. Prevents all other activation effects. -- ```BIONIC_SHOCKPROOF``` This bionic can't be incapacitated by electrical attacks. - +- `BIONIC_ARMOR_INTERFACE` This bionic can provide power to powered armor. +- `BIONIC_FAULTY` This bionic is a "faulty" bionic. +- `BIONIC_GUN` This bionic is a gun bionic and activating it will fire it. Prevents all other + activation effects. +- `BIONIC_NPC_USABLE` The NPC AI knows how to use this CBM and it can be installed on an NPC. +- `BIONIC_POWER_SOURCE` This bionic is a power source bionic. +- `BIONIC_SLEEP_FRIENDLY` This bionic won't prompt the user to turn it off if they try to sleep + while it's active. +- `BIONIC_TOGGLED` This bionic only has a function when activated, else it causes it's effect every + turn. +- `BIONIC_WEAPON` This bionic is a weapon bionic and activating it will create (or destroy) bionic's + fake_item in user's hands. Prevents all other activation effects. +- `BIONIC_SHOCKPROOF` This bionic can't be incapacitated by electrical attacks. ## Books -- ```INSPIRATIONAL``` Reading this book grants bonus morale to characters with the SPIRITUAL trait. +- `INSPIRATIONAL` Reading this book grants bonus morale to characters with the SPIRITUAL trait. ### Use actions -- ```ACIDBOMB_ACT``` Get rid of it or you'll end up like that guy in Robocop. -- ```ACIDBOMB``` Pull the pin on an acid bomb. -- ```AUTOCLAVE``` Sterilize one CBM by autoclaving it. -- ```ARROW_FLAMABLE``` Light your arrow and let fly. -- ```BELL``` Ring the bell. -- ```BOLTCUTTERS``` Use your town key to gain access anywhere. -- ```BREAK_STICK``` Breaks long stick into two. -- ```C4``` Arm the C4. -- ```CABLE_ATTACH``` This item is a cable spool. Use it to try to attach to a vehicle. -- ```CAN_GOO``` Release a little blob buddy. -- ```CAPTURE_MONSTER_ACT``` Capture and encapsulate a monster. The associated action is also used for releasing it. -- ```CARVER_OFF``` Turn the carver on. -- ```CARVER_ON``` Turn the carver off. -- ```CHAINSAW_OFF``` Turn the chainsaw on. -- ```CHAINSAW_ON``` Turn the chainsaw off. -- ```COMBATSAW_OFF``` Turn the combat-saw on. -- ```COMBATSAW_ON``` Turn the combat-saw off -- ```CROWBAR``` Pry open doors, windows, man-hole covers and many other things that need prying. -- ```DIG``` Clear rubble. -- ```DIRECTIONAL_ANTENNA``` Find the source of a signal with your radio. -- ```DIVE_TANK``` Use compressed air tank to breathe. -- ```DOG_WHISTLE``` Dogs hate this thing; your dog seems pretty cool with it though. -- ```DOLLCHAT``` That creepy doll just keeps on talking. -- ```ELEC_CHAINSAW_OFF``` Turn the electric chainsaw on. -- ```ELEC_CHAINSAW_ON``` Turn the electric chainsaw off. -- ```EXTINGUISHER``` Put out fires. -- ```FIRECRACKER_ACT``` The saddest Fourth of July. -- ```FIRECRACKER_PACK_ACT``` Keep the change you filthy animal. -- ```FIRECRACKER_PACK``` Light an entire packet of firecrackers. -- ```FIRECRACKER``` Light a singular firecracker. -- ```FLASHBANG``` Pull the pin on a flashbang. -- ```GEIGER``` Detect local radiation levels. -- ```GRANADE_ACT``` Assaults enemies with source code fixes? -- ```GRANADE``` Pull the pin on Granade. -- ```GRENADE``` Pull the pin on a grenade. -- ```HACKSAW``` Cut metal into chunks. -- ```HAMMER``` Pry boards off of windows, doors and fences. -- ```HEATPACK``` Activate the heatpack and get warm. -- ```HEAT_FOOD``` Heat food around fires. -- ```HOTPLATE``` Use the hotplate. -- ```JACKHAMMER``` Bust down walls and other constructions. -- ```JET_INJECTOR``` Inject some jet drugs right into your veins. -- ```LAW``` Unpack the LAW for firing. -- ```LIGHTSTRIP``` Activates the lightstrip. -- ```LUMBER``` Cut logs into planks. -- ```MAKEMOUND``` Make a mound of dirt. -- ```MANHACK``` Activate a manhack. -- ```MATCHBOMB``` Light the matchbomb. -- ```MILITARYMAP``` Learn of local military installations, and show roads. -- ```MININUKE``` Set the timer and run. Or hit with a hammer (not really). -- ```MOLOTOV_LIT``` Throw it, but don't drop it. -- ```MOLOTOV``` Light the Molotov cocktail. -- ```MOP``` Mop up the mess. -- ```MP3_ON``` Turn the mp3 player off. -- ```MP3``` Turn the mp3 player on. -- ```NOISE_EMITTER_OFF``` Turn the noise emitter on. -- ```NOISE_EMITTER_ON``` Turn the noise emitter off. -- ```NONE``` Do nothing. -- ```PACK_CBM``` Put CBM in special autoclave pouch so that they stay sterile once sterilized. -- ```PHEROMONE``` Makes zombies ignore you. -- ```PICKAXE``` Does nothing but berate you for having it (I'm serious). -- ```PLACE_RANDOMLY``` This is very much like the flag in the manhack iuse, it prevents the item from querying the player as to where they want the monster unloaded to, and instead choses randomly. -- ```PORTABLE_GAME``` Play games. -- ```PORTAL``` Create portal traps. -- ```RADIO_OFF``` Turn the radio on. -- ```RADIO_ON``` Turn the radio off. -- ```RAG``` Stop the bleeding. -- ```RESTAURANTMAP``` Learn of local eateries, and show roads. -- ```ROADMAP``` Learn of local common points-of-interest and show roads. -- ```SCISSORS``` Cut up clothing. -- ```SEED``` Asks if you are sure that you want to eat the seed. As it is better to plant seeds. -- ```SEW``` Sew clothing. -- ```SHELTER``` Put up a full-blown shelter. -- ```SHOCKTONFA_OFF``` Turn the shocktonfa on. -- ```SHOCKTONFA_ON``` Turn the shocktonfa off. -- ```SIPHON``` Siphon liquids out of vehicle. -- ```SMOKEBOMB_ACT``` This may be a good way to hide as a smoker. -- ```SMOKEBOMB``` Pull the pin on a smoke bomb. -- ```SOLARPACK_OFF``` Fold solar backpack array. -- ```SOLARPACK``` Unfold solar backpack array. -- ```SOLDER_WELD``` Solder or weld items, or cauterize wounds. -- ```SPRAY_CAN``` Graffiti the town. -- ```SURVIVORMAP``` Learn of local points-of-interest that can help you survive, and show roads. -- ```TAZER``` Shock someone or something. -- ```TELEPORT``` Teleport. -- ```TORCH``` Light a torch. -- ```TOURISTMAP``` Learn of local points-of-interest that a tourist would like to visit, and show roads. -- ```TOWEL``` Dry your character using the item as towel. -- ```TOW_ATTACH``` This is a tow cable, activate it to attach it to a vehicle. -- ```TURRET``` Activate a turret. -- ```WASH_ALL_ITEMS``` Wash items with FILTHY flag. -- ```WASH_HARD_ITEMS``` Wash hard items with FILTHY flag. -- ```WASH_SOFT_ITEMS``` Wash soft items with FILTHY flag. -- ```WATER_PURIFIER``` Purify water. - +- `ACIDBOMB_ACT` Get rid of it or you'll end up like that guy in Robocop. +- `ACIDBOMB` Pull the pin on an acid bomb. +- `AUTOCLAVE` Sterilize one CBM by autoclaving it. +- `ARROW_FLAMABLE` Light your arrow and let fly. +- `BELL` Ring the bell. +- `BOLTCUTTERS` Use your town key to gain access anywhere. +- `BREAK_STICK` Breaks long stick into two. +- `C4` Arm the C4. +- `CABLE_ATTACH` This item is a cable spool. Use it to try to attach to a vehicle. +- `CAN_GOO` Release a little blob buddy. +- `CAPTURE_MONSTER_ACT` Capture and encapsulate a monster. The associated action is also used for + releasing it. +- `CARVER_OFF` Turn the carver on. +- `CARVER_ON` Turn the carver off. +- `CHAINSAW_OFF` Turn the chainsaw on. +- `CHAINSAW_ON` Turn the chainsaw off. +- `COMBATSAW_OFF` Turn the combat-saw on. +- `COMBATSAW_ON` Turn the combat-saw off +- `CROWBAR` Pry open doors, windows, man-hole covers and many other things that need prying. +- `DIG` Clear rubble. +- `DIRECTIONAL_ANTENNA` Find the source of a signal with your radio. +- `DIVE_TANK` Use compressed air tank to breathe. +- `DOG_WHISTLE` Dogs hate this thing; your dog seems pretty cool with it though. +- `DOLLCHAT` That creepy doll just keeps on talking. +- `ELEC_CHAINSAW_OFF` Turn the electric chainsaw on. +- `ELEC_CHAINSAW_ON` Turn the electric chainsaw off. +- `EXTINGUISHER` Put out fires. +- `FIRECRACKER_ACT` The saddest Fourth of July. +- `FIRECRACKER_PACK_ACT` Keep the change you filthy animal. +- `FIRECRACKER_PACK` Light an entire packet of firecrackers. +- `FIRECRACKER` Light a singular firecracker. +- `FLASHBANG` Pull the pin on a flashbang. +- `GEIGER` Detect local radiation levels. +- `GRANADE_ACT` Assaults enemies with source code fixes? +- `GRANADE` Pull the pin on Granade. +- `GRENADE` Pull the pin on a grenade. +- `HACKSAW` Cut metal into chunks. +- `HAMMER` Pry boards off of windows, doors and fences. +- `HEATPACK` Activate the heatpack and get warm. +- `HEAT_FOOD` Heat food around fires. +- `HOTPLATE` Use the hotplate. +- `JACKHAMMER` Bust down walls and other constructions. +- `JET_INJECTOR` Inject some jet drugs right into your veins. +- `LAW` Unpack the LAW for firing. +- `LIGHTSTRIP` Activates the lightstrip. +- `LUMBER` Cut logs into planks. +- `MAKEMOUND` Make a mound of dirt. +- `MANHACK` Activate a manhack. +- `MATCHBOMB` Light the matchbomb. +- `MILITARYMAP` Learn of local military installations, and show roads. +- `MININUKE` Set the timer and run. Or hit with a hammer (not really). +- `MOLOTOV_LIT` Throw it, but don't drop it. +- `MOLOTOV` Light the Molotov cocktail. +- `MOP` Mop up the mess. +- `MP3_ON` Turn the mp3 player off. +- `MP3` Turn the mp3 player on. +- `NOISE_EMITTER_OFF` Turn the noise emitter on. +- `NOISE_EMITTER_ON` Turn the noise emitter off. +- `NONE` Do nothing. +- `PACK_CBM` Put CBM in special autoclave pouch so that they stay sterile once sterilized. +- `PHEROMONE` Makes zombies ignore you. +- `PICKAXE` Does nothing but berate you for having it (I'm serious). +- `PLACE_RANDOMLY` This is very much like the flag in the manhack iuse, it prevents the item from + querying the player as to where they want the monster unloaded to, and instead choses randomly. +- `PORTABLE_GAME` Play games. +- `PORTAL` Create portal traps. +- `RADIO_OFF` Turn the radio on. +- `RADIO_ON` Turn the radio off. +- `RAG` Stop the bleeding. +- `RESTAURANTMAP` Learn of local eateries, and show roads. +- `ROADMAP` Learn of local common points-of-interest and show roads. +- `SCISSORS` Cut up clothing. +- `SEED` Asks if you are sure that you want to eat the seed. As it is better to plant seeds. +- `SEW` Sew clothing. +- `SHELTER` Put up a full-blown shelter. +- `SHOCKTONFA_OFF` Turn the shocktonfa on. +- `SHOCKTONFA_ON` Turn the shocktonfa off. +- `SIPHON` Siphon liquids out of vehicle. +- `SMOKEBOMB_ACT` This may be a good way to hide as a smoker. +- `SMOKEBOMB` Pull the pin on a smoke bomb. +- `SOLARPACK_OFF` Fold solar backpack array. +- `SOLARPACK` Unfold solar backpack array. +- `SOLDER_WELD` Solder or weld items, or cauterize wounds. +- `SPRAY_CAN` Graffiti the town. +- `SURVIVORMAP` Learn of local points-of-interest that can help you survive, and show roads. +- `TAZER` Shock someone or something. +- `TELEPORT` Teleport. +- `TORCH` Light a torch. +- `TOURISTMAP` Learn of local points-of-interest that a tourist would like to visit, and show roads. +- `TOWEL` Dry your character using the item as towel. +- `TOW_ATTACH` This is a tow cable, activate it to attach it to a vehicle. +- `TURRET` Activate a turret. +- `WASH_ALL_ITEMS` Wash items with FILTHY flag. +- `WASH_HARD_ITEMS` Wash hard items with FILTHY flag. +- `WASH_SOFT_ITEMS` Wash soft items with FILTHY flag. +- `WATER_PURIFIER` Purify water. ## Comestibles ### Comestible type -- ```DRINK``` -- ```FOOD``` -- ```MED``` +- `DRINK` +- `FOOD` +- `MED` ### Addiction type -- ```alcohol``` -- ```amphetamine``` -- ```caffeine``` -- ```cocaine``` -- ```crack``` -- ```nicotine``` -- ```opiate``` -- ```sleeping pill``` +- `alcohol` +- `amphetamine` +- `caffeine` +- `cocaine` +- `crack` +- `nicotine` +- `opiate` +- `sleeping pill` ### Use action -- ```ALCOHOL_STRONG``` Greatly increases drunkenness. Adds disease `drunk`. -- ```ALCOHOL_WEAK``` Slightly increases drunkenness. Adds disease `drunk` -- ```ALCOHOL``` Increases drunkenness. Adds disease `drunk`. -- ```ANTIBIOTIC``` Helps fight infections. Removes disease `infected` and adds disease `recover`. -- ```BANDAGE``` Stop bleeding. -- ```BIRDFOOD``` Makes a small bird friendly. -- ```BLECH``` Causes vomiting. -- ```BLECH_BECAUSE_UNCLEAN``` Causes warning. -- ```CATFOOD``` Makes a cat friendly. -- ```CATTLEFODDER``` Makes a large herbivore friendly. -- ```CHEW``` Displays message "You chew your %s", but otherwise does nothing. -- ```CIG``` Alleviates nicotine cravings. Adds disease `cig`. -- ```COKE``` Decreases hunger. Adds disease `high`. -- ```CRACK``` Decreases hunger. Adds disease `high`. -- ```DISINFECTANT``` Prevents infections. -- ```DOGFOOD``` Makes a dog friendly. -- ```FIRSTAID``` Heal. -- ```FLUMED``` Adds disease `took_flumed`. -- ```FLUSLEEP``` Adds disease `took_flumed` and increases fatigue. -- ```FUNGICIDE``` Kills fungus and spores. Removes diseases `fungus` and `spores`. -- ```HALLU``` Adds disease `hallu`. -- ```HONEYCOMB``` Spawns wax. -- ```INHALER``` Removes disease `asthma`. -- ```IODINE``` Adds disease `iodine`. -- ```MARLOSS``` "As you eat the berry, you have a near-religious experience, feeling at one with your surroundings..." -- ```METH``` Adds disease `meth` -- ```NONE``` "You can't do anything of interest with your [x]." -- ```PKILL``` Reduces pain. Adds disease `pkill[n]` where `[n]` is the level of flag `PKILL_[n]` used on this comestible. -- ```PLANTBLECH``` Causes vomiting if player does not contain plant mutations -- ```POISON``` Adds diseases `poison` and `foodpoison`. -- ```PROZAC``` Adds disease `took_prozac` if not currently present, otherwise acts as a minor stimulant. Rarely has the `took_prozac_bad` adverse effect. -- ```PURIFIER``` Removes negative mutations. -- ```ROYAL_JELLY``` Alleviates many negative conditions and diseases. -- ```SEWAGE``` Causes vomiting and a chance to mutate. -- ```SLEEP``` Greatly increases fatigue. -- ```THORAZINE``` Removes diseases `hallu`, `visuals`, `high`. Additionally removes disease `formication` if disease `dermatik` isn't also present. Has a chance of a negative reaction which increases fatigue. -- ```VACCINE``` Greatly increases health. -- ```VITAMINS``` Increases healthiness (not to be confused with HP) -- ```WEED``` Makes you roll with Cheech & Chong. Adds disease `weed_high`. -- ```XANAX``` Alleviates anxiety. Adds disease `took_xanax`. +- `ALCOHOL_STRONG` Greatly increases drunkenness. Adds disease `drunk`. +- `ALCOHOL_WEAK` Slightly increases drunkenness. Adds disease `drunk` +- `ALCOHOL` Increases drunkenness. Adds disease `drunk`. +- `ANTIBIOTIC` Helps fight infections. Removes disease `infected` and adds disease `recover`. +- `BANDAGE` Stop bleeding. +- `BIRDFOOD` Makes a small bird friendly. +- `BLECH` Causes vomiting. +- `BLECH_BECAUSE_UNCLEAN` Causes warning. +- `CATFOOD` Makes a cat friendly. +- `CATTLEFODDER` Makes a large herbivore friendly. +- `CHEW` Displays message "You chew your %s", but otherwise does nothing. +- `CIG` Alleviates nicotine cravings. Adds disease `cig`. +- `COKE` Decreases hunger. Adds disease `high`. +- `CRACK` Decreases hunger. Adds disease `high`. +- `DISINFECTANT` Prevents infections. +- `DOGFOOD` Makes a dog friendly. +- `FIRSTAID` Heal. +- `FLUMED` Adds disease `took_flumed`. +- `FLUSLEEP` Adds disease `took_flumed` and increases fatigue. +- `FUNGICIDE` Kills fungus and spores. Removes diseases `fungus` and `spores`. +- `HALLU` Adds disease `hallu`. +- `HONEYCOMB` Spawns wax. +- `INHALER` Removes disease `asthma`. +- `IODINE` Adds disease `iodine`. +- `MARLOSS` "As you eat the berry, you have a near-religious experience, feeling at one with your + surroundings..." +- `METH` Adds disease `meth` +- `NONE` "You can't do anything of interest with your [x]." +- `PKILL` Reduces pain. Adds disease `pkill[n]` where `[n]` is the level of flag `PKILL_[n]` used on + this comestible. +- `PLANTBLECH` Causes vomiting if player does not contain plant mutations +- `POISON` Adds diseases `poison` and `foodpoison`. +- `PROZAC` Adds disease `took_prozac` if not currently present, otherwise acts as a minor stimulant. + Rarely has the `took_prozac_bad` adverse effect. +- `PURIFIER` Removes negative mutations. +- `ROYAL_JELLY` Alleviates many negative conditions and diseases. +- `SEWAGE` Causes vomiting and a chance to mutate. +- `SLEEP` Greatly increases fatigue. +- `THORAZINE` Removes diseases `hallu`, `visuals`, `high`. Additionally removes disease + `formication` if disease `dermatik` isn't also present. Has a chance of a negative reaction which + increases fatigue. +- `VACCINE` Greatly increases health. +- `VITAMINS` Increases healthiness (not to be confused with HP) +- `WEED` Makes you roll with Cheech & Chong. Adds disease `weed_high`. +- `XANAX` Alleviates anxiety. Adds disease `took_xanax`. ### Flags -- ```ACID``` when consumed using the BLECH function, penalties are reduced if acidproof. -- ```CARNIVORE_OK``` Can be eaten by characters with the Carnivore mutation. -- ```CANT_HEAL_EVERYONE``` This med can't be used by everyone, it require a special mutation. See `can_heal_with` in mutation. -- ```EATEN_COLD``` Morale bonus for eating cold. -- ```EATEN_HOT``` Morale bonus for eating hot. -- ```INEDIBLE``` Inedible by default, enabled to eat when in conjunction with (mutation threshold) flags: BIRD, CATTLE. -- ```FERTILIZER``` Works as fertilizer for farming, of if this consumed with the PLANTBLECH function penalties will be reversed for plants. -- ```FREEZERBURN``` First thaw is MUSHY, second is rotten -- ```FUNGAL_VECTOR``` Will give a fungal infection when consumed. -- ```HIDDEN_HALLU``` ... Food causes hallucinations, visible only with a certain survival skill level. -- ```HIDDEN_POISON``` ... Food displays as poisonous with a certain survival skill level. Note that this doesn't make items poisonous on its own, consider adding `"use_action": "POISON"` as well, or using `FORAGE_POISON` instead. -- ```MELTS``` Provides half fun unless frozen. Edible when frozen. -- ```MILLABLE``` Can be placed inside a mill, to turn into flour. -- ```MYCUS_OK``` Can be eaten by post-threshold Mycus characters. Only applies to mycus fruits by default. -- ```NEGATIVE_MONOTONY_OK``` Allows ```negative_monotony``` property to lower comestible fun to negative values. -- ```NO_INGEST``` Administered by some means other than oral intake. -- ```PKILL_1``` Minor painkiller. -- ```PKILL_2``` Moderate painkiller. -- ```PKILL_3``` Heavy painkiller. -- ```PKILL_4``` "You shoot up." -- ```PKILL_L``` Slow-release painkiller. -- ```RAW``` Reduces kcal by 25%, until cooked (that is, used in a recipe that requires a heat source). Should be added to *all* uncooked food, unless that food derives more than 50% of its calories from sugars (i.e. many fruits, some veggies) or fats (i.e. butchered fat, coconut). TODO: Make a unit test for these criteria after fat/protein/carbs are added. -- ```SMOKABLE``` Accepted by smoking rack. -- ```SMOKED``` Not accepted by smoking rack (product of smoking). -- ```USE_EAT_VERB``` "You drink your %s." or "You eat your %s." -- ```USE_ON_NPC``` Can be used on NPCs (not necessarily by them). -- ```ZOOM``` Zoom items can increase your overmap sight range. +- `ACID` when consumed using the BLECH function, penalties are reduced if acidproof. +- `CARNIVORE_OK` Can be eaten by characters with the Carnivore mutation. +- `CANT_HEAL_EVERYONE` This med can't be used by everyone, it require a special mutation. See + `can_heal_with` in mutation. +- `EATEN_COLD` Morale bonus for eating cold. +- `EATEN_HOT` Morale bonus for eating hot. +- `INEDIBLE` Inedible by default, enabled to eat when in conjunction with (mutation threshold) + flags: BIRD, CATTLE. +- `FERTILIZER` Works as fertilizer for farming, of if this consumed with the PLANTBLECH function + penalties will be reversed for plants. +- `FREEZERBURN` First thaw is MUSHY, second is rotten +- `FUNGAL_VECTOR` Will give a fungal infection when consumed. +- `HIDDEN_HALLU` ... Food causes hallucinations, visible only with a certain survival skill level. +- `HIDDEN_POISON` ... Food displays as poisonous with a certain survival skill level. Note that this + doesn't make items poisonous on its own, consider adding `"use_action": "POISON"` as well, or + using `FORAGE_POISON` instead. +- `MELTS` Provides half fun unless frozen. Edible when frozen. +- `MILLABLE` Can be placed inside a mill, to turn into flour. +- `MYCUS_OK` Can be eaten by post-threshold Mycus characters. Only applies to mycus fruits by + default. +- `NEGATIVE_MONOTONY_OK` Allows `negative_monotony` property to lower comestible fun to negative + values. +- `NO_INGEST` Administered by some means other than oral intake. +- `PKILL_1` Minor painkiller. +- `PKILL_2` Moderate painkiller. +- `PKILL_3` Heavy painkiller. +- `PKILL_4` "You shoot up." +- `PKILL_L` Slow-release painkiller. +- `RAW` Reduces kcal by 25%, until cooked (that is, used in a recipe that requires a heat source). + Should be added to _all_ uncooked food, unless that food derives more than 50% of its calories + from sugars (i.e. many fruits, some veggies) or fats (i.e. butchered fat, coconut). TODO: Make a + unit test for these criteria after fat/protein/carbs are added. +- `SMOKABLE` Accepted by smoking rack. +- `SMOKED` Not accepted by smoking rack (product of smoking). +- `USE_EAT_VERB` "You drink your %s." or "You eat your %s." +- `USE_ON_NPC` Can be used on NPCs (not necessarily by them). +- `ZOOM` Zoom items can increase your overmap sight range. ## Furniture and Terrain @@ -505,325 +563,388 @@ List of known flags, used in both `terrain.json` and `furniture.json`. ### Flags -- ```ALARMED``` Sets off an alarm if smashed. -- ```ALLOW_FIELD_EFFECT``` Apply field effects to items inside ```SEALED``` terrain/furniture. -- ```AUTO_WALL_SYMBOL``` (only for terrain) The symbol of this terrain will be one of the line drawings (corner, T-intersection, straight line etc.) depending on the adjacent terrains. - - Example: `-` and `|` are both terrain with the `CONNECT_TO_WALL` flag. `O` does not have the flag, while `X` and `Y` have the `AUTO_WALL_SYMBOL` flag. - - `X` terrain will be drawn as a T-intersection (connected to west, south and east), `Y` will be drawn as horizontal line (going from west to east, no connection to south). - ``` - -X- -Y- - | O - ``` - -- ```BARRICADABLE_DOOR_DAMAGED``` -- ```BARRICADABLE_DOOR_REINFORCED_DAMAGED``` -- ```BARRICADABLE_DOOR_REINFORCED``` -- ```BARRICADABLE_DOOR``` Door that can be barricaded. -- ```BARRICADABLE_WINDOW_CURTAINS``` -- ```BARRICADABLE_WINDOW``` Window that can be barricaded. -- ```BASHABLE``` Players + Monsters can bash this. -- ```BLOCK_WIND``` This terrain will block the effects of wind. -- ```BURROWABLE``` Burrowing monsters can travel under this terrain, while most others can't (e.g. graboid will traverse under the chain link fence, while ordinary zombie will be stopped by it). -- ```BUTCHER_EQ``` Butcher's equipment - required for full butchery of corpses. -- ```CAN_SIT``` Furniture the player can sit on. Player sitting near furniture with the "FLAT_SURF" tag will get mood bonus for eating. -- ```CHIP``` Used in construction menu to determine if wall can have paint chipped off. -- ```COLLAPSES``` Has a roof that can collapse. -- ```CONNECT_TO_WALL``` (only for terrain) This flag has been superseded by the JSON entry `connects_to`, but is retained for backward compatibility. -- ```CONSOLE``` Used as a computer. -- ```CONTAINER``` Items on this square are hidden until looted by the player. -- ```DECONSTRUCT``` Can be deconstructed. -- ```DEEP_WATER``` -- ```DESTROY_ITEM``` Items that land here are destroyed. See also `NOITEM` -- ```DIFFICULT_Z``` Most zombies will not be able to follow you up this terrain ( i.e a ladder ) -- ```DIGGABLE_CAN_DEEPEN``` Diggable location can be dug again to make deeper (e.g. shallow pit to deep pit). -- ```DIGGABLE``` Digging monsters, seeding monster, digging with shovel, etc. -- ```DOOR``` Can be opened (used for NPC path-finding). -- ```EASY_DECONSTRUCT``` Player can deconstruct this without tools. -- ```ELEVATOR``` Terrain with this flag will move player, NPCs, monsters, and items up and down when player activates nearby `elevator controls`. -- ```EMITTER``` This furniture will emit fields automatically as defined by its emissions entry -- ```FIRE_CONTAINER``` Stops fire from spreading (brazier, wood stove, etc.) -- ```FLAMMABLE_ASH``` Burns to ash rather than rubble. -- ```FLAMMABLE_HARD``` Harder to light on fire, but still possible. -- ```FLAMMABLE``` Can be lit on fire. -- ```FLAT_SURF``` Furniture or terrain with a flat hard surface (e.g. table, but not chair; tree stump, etc.). -- ```FLAT``` Player can build and move furniture on. -- ```FORAGE_HALLU``` This item can be found with the `HIDDEN_HALLU` flag when found through foraging. -- ```FORAGE_POISION``` This item can be found with the `HIDDEN_POISON` flag when found through foraging. -- ```FRIDGE``` This item refrigerates items inside. Preserving them. Unlike vehicle parts, any furniture with this flag constantly functions. -- ```FREEZER``` This item freezes items inside. Preserving them extremely well. Unlike vehicle parts, any furniture with this flag constantly functions. -- ```GOES_DOWN``` Can use > to go down a level. -- ```GOES_UP``` Can use < to go up a level. -- ```GROWTH_SEED``` This plant is in its seed stage of growth. -- ```GROWTH_SEEDLING``` This plant is in its seedling stage of growth. -- ```GROWTH_MATURE``` This plant is in a mature stage of a growth. -- ```GROWTH_HARVEST``` This plant is ready for harvest. -- ```HARVESTED``` Marks the harvested version of a terrain type (e.g. harvesting an apple tree turns it into a harvested tree, which later becomes an apple tree again). -- ```HIDE_PLACE``` Creatures on this tile can't be seen by creatures not standing on adjacent tiles -- ```INDOORS``` Has a roof over it; blocks rain, sunlight, etc. -- ```LADDER``` This piece of furniture that makes climbing easy (works only with z-level mode). -- ```LIQUIDCONT``` Furniture that contains liquid, allows for contents to be accessed in some checks even if `SEALED`. -- ```LIQUID``` Blocks movement, but isn't a wall (lava, water, etc.) -- ```MINEABLE``` Can be mined with a pickaxe/jackhammer. -- ```MOUNTABLE``` Suitable for guns with the `MOUNTED_GUN` flag. -- ```NOCOLLIDE``` Feature that simply doesn't collide with vehicles at all. -- ```NOITEM``` Items cannot be added here but may overflow to adjacent tiles. See also `DESTROY_ITEM` -- ```NO_FLOOR``` Things should fall when placed on this tile -- ```NO_SIGHT``` Creature on this tile have their sight reduced to one tile -- ```NO_SCENT``` This tile cannot have scent values, which prevents scent diffusion through this tile -- ```OPENCLOSE_INSIDE``` If it's a door (with an 'open' or 'close' field), it can only be opened or closed if you're inside. -- ```PAINFUL``` May cause a small amount of pain. -- ```PERMEABLE``` Permeable for gases. -- ```PLACE_ITEM``` Valid terrain for `place_item()` to put items on. -- ```PLANT``` A 'furniture' that grows and fruits. -- ```PLANTABLE``` This terrain or furniture can have seeds planted in it. -- ```PLOWABLE``` Terrain can be plowed. -- ```RAMP_END``` -- ```RAMP``` Can be used to move up a z-level -- ```REDUCE_SCENT``` Reduces scent diffusion (not total amount of scent in area); only works if also bashable. -- ```ROAD``` Flat and hard enough to drive or skate (with rollerblades) on. -- ```ROUGH``` May hurt the player's feet. -- ```RUG``` Enables the `Remove Carpet` Construction entry. -- ```SALT_WATER``` Source of salt water (works for terrains with examine action "water_source"). -- ```SEALED``` Can't use e to retrieve items; must smash them open first. -- ```SEEN_FROM_ABOVE``` Visible from a higher level (provided the tile above has no floor) -- ```SHARP``` May do minor damage to players/monsters passing through it. -- ```SHORT``` Feature too short to collide with vehicle protrusions. (mirrors, blades). -- ```SIGN``` Show written message on examine. -- ```SMALL_PASSAGE``` This terrain or furniture is too small for large or huge creatures to pass through. -- ```SUN_ROOF_ABOVE``` This furniture (terrain is not supported currently) has a "fake roof" above, that blocks sunlight. Special hack for #44421, to be removed later. -- ```SUPPORTS_ROOF``` Used as a boundary for roof construction. -- ```SUPPRESS_SMOKE``` Prevents smoke from fires; used by ventilated wood stoves, etc. -- ```SWIMMABLE``` Player and monsters can swim through it. -- ```THIN_OBSTACLE``` Passable by players and monsters; vehicles destroy it. -- ```TINY``` Feature too short to collide with vehicle undercarriage. Vehicles drive over them with no damage, unless a wheel hits them. -- ```TRANSPARENT``` Players and monsters can see through/past it. Also sets ter_t.transparent. -- ```UNSTABLE``` Walking here cause the bouldering effect on the character. -- ```USABLE_FIRE``` This terrain or furniture counts as a nearby fire for crafting. -- ```VEH_TREAT_AS_BASH_BELOW``` Vehicles will not collide with this even if it counts as rough terrain, like floor with bash_below does. Used for terrain meant to be turned into other terrain when smashed instead of destroying the tile beneath it. -- ```WALL``` This terrain is an upright obstacle. Used for fungal conversion, and also implies `CONNECT_TO_WALL`. +- `ALARMED` Sets off an alarm if smashed. +- `ALLOW_FIELD_EFFECT` Apply field effects to items inside `SEALED` terrain/furniture. +- `AUTO_WALL_SYMBOL` (only for terrain) The symbol of this terrain will be one of the line drawings + (corner, T-intersection, straight line etc.) depending on the adjacent terrains. + + Example: `-` and `|` are both terrain with the `CONNECT_TO_WALL` flag. `O` does not have the flag, + while `X` and `Y` have the `AUTO_WALL_SYMBOL` flag. + + `X` terrain will be drawn as a T-intersection (connected to west, south and east), `Y` will be + drawn as horizontal line (going from west to east, no connection to south). + ``` + -X- -Y- + | O + ``` + +- `BARRICADABLE_DOOR_DAMAGED` +- `BARRICADABLE_DOOR_REINFORCED_DAMAGED` +- `BARRICADABLE_DOOR_REINFORCED` +- `BARRICADABLE_DOOR` Door that can be barricaded. +- `BARRICADABLE_WINDOW_CURTAINS` +- `BARRICADABLE_WINDOW` Window that can be barricaded. +- `BASHABLE` Players + Monsters can bash this. +- `BLOCK_WIND` This terrain will block the effects of wind. +- `BURROWABLE` Burrowing monsters can travel under this terrain, while most others can't (e.g. + graboid will traverse under the chain link fence, while ordinary zombie will be stopped by it). +- `BUTCHER_EQ` Butcher's equipment - required for full butchery of corpses. +- `CAN_SIT` Furniture the player can sit on. Player sitting near furniture with the "FLAT_SURF" tag + will get mood bonus for eating. +- `CHIP` Used in construction menu to determine if wall can have paint chipped off. +- `COLLAPSES` Has a roof that can collapse. +- `CONNECT_TO_WALL` (only for terrain) This flag has been superseded by the JSON entry + `connects_to`, but is retained for backward compatibility. +- `CONSOLE` Used as a computer. +- `CONTAINER` Items on this square are hidden until looted by the player. +- `DECONSTRUCT` Can be deconstructed. +- `DEEP_WATER` +- `DESTROY_ITEM` Items that land here are destroyed. See also `NOITEM` +- `DIFFICULT_Z` Most zombies will not be able to follow you up this terrain ( i.e a ladder ) +- `DIGGABLE_CAN_DEEPEN` Diggable location can be dug again to make deeper (e.g. shallow pit to deep + pit). +- `DIGGABLE` Digging monsters, seeding monster, digging with shovel, etc. +- `DOOR` Can be opened (used for NPC path-finding). +- `EASY_DECONSTRUCT` Player can deconstruct this without tools. +- `ELEVATOR` Terrain with this flag will move player, NPCs, monsters, and items up and down when + player activates nearby `elevator controls`. +- `EMITTER` This furniture will emit fields automatically as defined by its emissions entry +- `FIRE_CONTAINER` Stops fire from spreading (brazier, wood stove, etc.) +- `FLAMMABLE_ASH` Burns to ash rather than rubble. +- `FLAMMABLE_HARD` Harder to light on fire, but still possible. +- `FLAMMABLE` Can be lit on fire. +- `FLAT_SURF` Furniture or terrain with a flat hard surface (e.g. table, but not chair; tree stump, + etc.). +- `FLAT` Player can build and move furniture on. +- `FORAGE_HALLU` This item can be found with the `HIDDEN_HALLU` flag when found through foraging. +- `FORAGE_POISION` This item can be found with the `HIDDEN_POISON` flag when found through foraging. +- `FRIDGE` This item refrigerates items inside. Preserving them. Unlike vehicle parts, any furniture + with this flag constantly functions. +- `FREEZER` This item freezes items inside. Preserving them extremely well. Unlike vehicle parts, + any furniture with this flag constantly functions. +- `GOES_DOWN` Can use > to go down a level. +- `GOES_UP` Can use < to go up a level. +- `GROWTH_SEED` This plant is in its seed stage of growth. +- `GROWTH_SEEDLING` This plant is in its seedling stage of growth. +- `GROWTH_MATURE` This plant is in a mature stage of a growth. +- `GROWTH_HARVEST` This plant is ready for harvest. +- `HARVESTED` Marks the harvested version of a terrain type (e.g. harvesting an apple tree turns it + into a harvested tree, which later becomes an apple tree again). +- `HIDE_PLACE` Creatures on this tile can't be seen by creatures not standing on adjacent tiles +- `INDOORS` Has a roof over it; blocks rain, sunlight, etc. +- `LADDER` This piece of furniture that makes climbing easy (works only with z-level mode). +- `LIQUIDCONT` Furniture that contains liquid, allows for contents to be accessed in some checks + even if `SEALED`. +- `LIQUID` Blocks movement, but isn't a wall (lava, water, etc.) +- `MINEABLE` Can be mined with a pickaxe/jackhammer. +- `MOUNTABLE` Suitable for guns with the `MOUNTED_GUN` flag. +- `NOCOLLIDE` Feature that simply doesn't collide with vehicles at all. +- `NOITEM` Items cannot be added here but may overflow to adjacent tiles. See also `DESTROY_ITEM` +- `NO_FLOOR` Things should fall when placed on this tile +- `NO_SIGHT` Creature on this tile have their sight reduced to one tile +- `NO_SCENT` This tile cannot have scent values, which prevents scent diffusion through this tile +- `OPENCLOSE_INSIDE` If it's a door (with an 'open' or 'close' field), it can only be opened or + closed if you're inside. +- `PAINFUL` May cause a small amount of pain. +- `PERMEABLE` Permeable for gases. +- `PLACE_ITEM` Valid terrain for `place_item()` to put items on. +- `PLANT` A 'furniture' that grows and fruits. +- `PLANTABLE` This terrain or furniture can have seeds planted in it. +- `PLOWABLE` Terrain can be plowed. +- `RAMP_END` +- `RAMP` Can be used to move up a z-level +- `REDUCE_SCENT` Reduces scent diffusion (not total amount of scent in area); only works if also + bashable. +- `ROAD` Flat and hard enough to drive or skate (with rollerblades) on. +- `ROUGH` May hurt the player's feet. +- `RUG` Enables the `Remove Carpet` Construction entry. +- `SALT_WATER` Source of salt water (works for terrains with examine action "water_source"). +- `SEALED` Can't use e to retrieve items; must smash them open first. +- `SEEN_FROM_ABOVE` Visible from a higher level (provided the tile above has no floor) +- `SHARP` May do minor damage to players/monsters passing through it. +- `SHORT` Feature too short to collide with vehicle protrusions. (mirrors, blades). +- `SIGN` Show written message on examine. +- `SMALL_PASSAGE` This terrain or furniture is too small for large or huge creatures to pass + through. +- `SUN_ROOF_ABOVE` This furniture (terrain is not supported currently) has a "fake roof" above, that + blocks sunlight. Special hack for #44421, to be removed later. +- `SUPPORTS_ROOF` Used as a boundary for roof construction. +- `SUPPRESS_SMOKE` Prevents smoke from fires; used by ventilated wood stoves, etc. +- `SWIMMABLE` Player and monsters can swim through it. +- `THIN_OBSTACLE` Passable by players and monsters; vehicles destroy it. +- `TINY` Feature too short to collide with vehicle undercarriage. Vehicles drive over them with no + damage, unless a wheel hits them. +- `TRANSPARENT` Players and monsters can see through/past it. Also sets ter_t.transparent. +- `UNSTABLE` Walking here cause the bouldering effect on the character. +- `USABLE_FIRE` This terrain or furniture counts as a nearby fire for crafting. +- `VEH_TREAT_AS_BASH_BELOW` Vehicles will not collide with this even if it counts as rough terrain, + like floor with bash_below does. Used for terrain meant to be turned into other terrain when + smashed instead of destroying the tile beneath it. +- `WALL` This terrain is an upright obstacle. Used for fungal conversion, and also implies + `CONNECT_TO_WALL`. ### Examine Actions -- ```aggie_plant``` Harvest plants. -- ```autodoc``` Brings the autodoc consoles menu. Needs the ```AUTODOC``` flag to function properly and an adjacent furniture with the ```AUTODOC_COUCH``` flag. -- ```autoclave_empty``` Start the autoclave cycle if it contains filthy CBM, and the player has enough water. -- ```autoclave_full``` Check on the progress of the cycle, and collect sterile CBM once cycle is completed. -- ```bars``` Take advantage of AMORPHOUS and slip through the bars. -- ```bulletin_board``` Use this to arrange tasks for your faction camp. -- ```cardreader``` Use the cardreader with a valid card, or attempt to hack. -- ```chainfence``` Hop over the chain fence. -- ```controls_gate``` Controls the attached gate. -- ```dirtmound``` Plant seeds and plants. -- ```elevator``` Use the elevator to change floors. -- ```fault``` Displays descriptive message, but otherwise unused. -- ```flower_poppy``` Pick the mutated poppy. -- ```fswitch``` Flip the switch and the rocks will shift. -- ```fungus``` Release spores as the terrain crumbles away. -- ```gaspump``` Use the gas-pump. -- ```none``` None -- ```pedestal_temple``` Opens the temple if you have a petrified eye. -- ```pedestal_wyrm``` Spawn wyrms. -- ```pit_covered``` Uncover the pit. -- ```pit``` Cover the pit if you have some planks of wood. -- ```portable_structure``` Take down a tent or similar portable structure. -- ```recycle_compactor``` Compress pure metal objects into basic shapes. -- ```rubble``` Clear up the rubble if you have a shovel. -- ```safe``` Attempt to crack the safe. -- ```shelter``` Take down the shelter. -- ```shrub_marloss``` Pick a marloss bush. -- ```shrub_wildveggies``` Pick a wild veggies shrub. -- ```slot_machine``` Gamble. -- ```toilet``` Either drink or get water out of the toilet. -- ```trap``` Interact with a trap. -- ```water_source``` Drink or get water from a water source. +- `aggie_plant` Harvest plants. +- `autodoc` Brings the autodoc consoles menu. Needs the `AUTODOC` flag to function properly and an + adjacent furniture with the `AUTODOC_COUCH` flag. +- `autoclave_empty` Start the autoclave cycle if it contains filthy CBM, and the player has enough + water. +- `autoclave_full` Check on the progress of the cycle, and collect sterile CBM once cycle is + completed. +- `bars` Take advantage of AMORPHOUS and slip through the bars. +- `bulletin_board` Use this to arrange tasks for your faction camp. +- `cardreader` Use the cardreader with a valid card, or attempt to hack. +- `chainfence` Hop over the chain fence. +- `controls_gate` Controls the attached gate. +- `dirtmound` Plant seeds and plants. +- `elevator` Use the elevator to change floors. +- `fault` Displays descriptive message, but otherwise unused. +- `flower_poppy` Pick the mutated poppy. +- `fswitch` Flip the switch and the rocks will shift. +- `fungus` Release spores as the terrain crumbles away. +- `gaspump` Use the gas-pump. +- `none` None +- `pedestal_temple` Opens the temple if you have a petrified eye. +- `pedestal_wyrm` Spawn wyrms. +- `pit_covered` Uncover the pit. +- `pit` Cover the pit if you have some planks of wood. +- `portable_structure` Take down a tent or similar portable structure. +- `recycle_compactor` Compress pure metal objects into basic shapes. +- `rubble` Clear up the rubble if you have a shovel. +- `safe` Attempt to crack the safe. +- `shelter` Take down the shelter. +- `shrub_marloss` Pick a marloss bush. +- `shrub_wildveggies` Pick a wild veggies shrub. +- `slot_machine` Gamble. +- `toilet` Either drink or get water out of the toilet. +- `trap` Interact with a trap. +- `water_source` Drink or get water from a water source. ### Fungal Conversions Only -- ```FLOWER``` This furniture is a flower. -- ```FUNGUS``` Fungal covered. -- ```ORGANIC``` This furniture is partly organic. -- ```SHRUB``` This terrain is a shrub. -- ```TREE``` This terrain is a tree. -- ```YOUNG``` This terrain is a young tree. +- `FLOWER` This furniture is a flower. +- `FUNGUS` Fungal covered. +- `ORGANIC` This furniture is partly organic. +- `SHRUB` This terrain is a shrub. +- `TREE` This terrain is a tree. +- `YOUNG` This terrain is a young tree. ### Furniture Only -- ```AUTODOC``` This furniture can be an autodoc console, it also needs the ```autodoc``` examine action. -- ```AUTODOC_COUCH``` This furniture can be a couch for a furniture with the ```autodoc``` examine action. -- ```BLOCKSDOOR``` This will boost map terrain's resistance to bashing if `str_*_blocked` is set (see `map_bash_info`) - +- `AUTODOC` This furniture can be an autodoc console, it also needs the `autodoc` examine action. +- `AUTODOC_COUCH` This furniture can be a couch for a furniture with the `autodoc` examine action. +- `BLOCKSDOOR` This will boost map terrain's resistance to bashing if `str_*_blocked` is set (see + `map_bash_info`) ## Generic ### Flags -- ```BIONIC_NPC_USABLE``` ... Safe CBMs that NPCs can use without extensive NPC rewrites to utilize toggle CBMs. -- ```BIONIC_TOGGLED``` ... This bionic only has a function when activated, instead of causing its effect every turn. -- ```BIONIC_POWER_SOURCE``` ... This bionic is a source of bionic power. -- ```BIONIC_SHOCKPROOF``` ... This bionic can't be incapacitated by electrical attacks. -- ```BIONIC_FAULTY``` ... This bionic is a "faulty" bionic. -- ```BIONIC_WEAPON``` ... This bionic is a weapon bionic and activating it will create (or destroy) bionic's fake_item in user's hands. Prevents all other activation effects. -- ```BIONIC_ARMOR_INTERFACE``` ... This bionic can provide power to powered armor. -- ```BIONIC_SLEEP_FRIENDLY``` ... This bionic won't provide a warning if the player tries to sleep while it's active. -- ```BIONIC_GUN``` ... This bionic is a gun bionic and activating it will fire it. Prevents all other activation effects. -- ```CORPSE``` ... Flag used to spawn various human corpses during the mapgen. -- ```DANGEROUS``` ... NPCs will not accept this item. Explosion iuse actor implies this flag. Implies "NPC_THROW_NOW". -- ```DETERGENT``` ... This item can be used as a detergent in a washing machine. -- ```DURABLE_MELEE``` ... Item is made to hit stuff and it does it well, so it's considered to be a lot tougher than other weapons made of the same materials. -- ```FAKE_MILL``` ... Item is a fake item, to denote a partially milled product by @ref Item::process_fake_mill, where conditions for its removal are set. -- ```FAKE_SMOKE``` ... Item is a fake item generating smoke, recognizable by @ref item::process_fake_smoke, where conditions for its removal are set. -- ```FIREWOOD``` ... This item can serve as a firewood. Items with this flag are sorted out to "Loot: Wood" zone -- ```FRAGILE_MELEE``` ... Fragile items that fall apart easily when used as a weapon due to poor construction quality and will break into components when broken. -- ```GAS_DISCOUNT``` ... Discount cards for the automated gas stations. -- ```IS_PET_ARMOR``` ... Is armor for a pet monster, not armor for a person -- ```LEAK_ALWAYS``` ... Leaks (may be combined with "RADIOACTIVE"). -- ```LEAK_DAM``` ... Leaks when damaged (may be combined with "RADIOACTIVE"). -- ```NEEDS_UNFOLD``` ... Has an additional time penalty upon wielding. For melee weapons and guns this is offset by the relevant skill. Stacks with "SLOW_WIELD". -- ```NO_PACKED``` ... This item is not protected against contamination and won't stay sterile. Only applies to CBMs. -- ```NO_REPAIR``` ... Prevents repairing of this item even if otherwise suitable tools exist. -- ```NO_SALVAGE``` ... Item cannot be broken down through a salvage process. Best used when something should not be able to be broken down (i.e. base components like leather patches). -- ```NO_STERILE``` ... This item is not sterile. Only applies to CBMs. -- ```NPC_ACTIVATE``` ... NPCs can activate this item as an alternative attack. Currently by throwing it right after activation. Implied by "BOMB". -- ```NPC_ALT_ATTACK``` ... Shouldn't be set directly. Implied by "NPC_ACTIVATE" and "NPC_THROWN". -- ```NPC_THROWN``` ... NPCs will throw this item (without activating it first) as an alternative attack. -- ```NPC_THROW_NOW``` ... NPCs will try to throw this item away, preferably at enemies. Implies "TRADER_AVOID" and "NPC_THROWN". -- ```PSEUDO``` ... Used internally to mark items that are referred to in the crafting inventory but are not actually items. They can be used as tools, but not as components. Implies "TRADER_AVOID". -- ```RADIOACTIVE``` ... Is radioactive (can be used with LEAK_*). -- ```RAIN_PROTECT``` ... Protects from sunlight and from rain, when wielded. -- ```REDUCED_BASHING``` ... Gunmod flag; reduces the item's bashing damage by 50%. -- ```REDUCED_WEIGHT``` ... Gunmod flag; reduces the item's base weight by 25%. -- ```REQUIRES_TINDER``` ... Requires tinder to be present on the tile this item tries to start a fire on. -- ```SLEEP_AID``` ... This item helps in sleeping. -- ```SLEEP_IGNORE``` ... This item is not shown as before-sleep warning. -- ```SLOW_WIELD``` ... Has an additional time penalty upon wielding. For melee weapons and guns this is offset by the relevant skill. Stacks with "NEEDS_UNFOLD". -- ```TACK``` ... Item can be used as tack for a mount. -- ```TIE_UP``` ... Item can be used to tie up a creature. -- ```TINDER``` ... This item can be used as tinder for lighting a fire with a REQUIRES_TINDER flagged firestarter. -- ```TRADER_AVOID``` ... NPCs will not start with this item. Use this for active items (e.g. flashlight (on)), dangerous items (e.g. active bomb), fake item or unusual items (e.g. unique quest item). -- ```UNBREAKABLE_MELEE``` ... Does never get damaged when used as melee weapon. -- ```UNRECOVERABLE``` ... Cannot be recovered from a disassembly. - +- `BIONIC_NPC_USABLE` ... Safe CBMs that NPCs can use without extensive NPC rewrites to utilize + toggle CBMs. +- `BIONIC_TOGGLED` ... This bionic only has a function when activated, instead of causing its effect + every turn. +- `BIONIC_POWER_SOURCE` ... This bionic is a source of bionic power. +- `BIONIC_SHOCKPROOF` ... This bionic can't be incapacitated by electrical attacks. +- `BIONIC_FAULTY` ... This bionic is a "faulty" bionic. +- `BIONIC_WEAPON` ... This bionic is a weapon bionic and activating it will create (or destroy) + bionic's fake_item in user's hands. Prevents all other activation effects. +- `BIONIC_ARMOR_INTERFACE` ... This bionic can provide power to powered armor. +- `BIONIC_SLEEP_FRIENDLY` ... This bionic won't provide a warning if the player tries to sleep while + it's active. +- `BIONIC_GUN` ... This bionic is a gun bionic and activating it will fire it. Prevents all other + activation effects. +- `CORPSE` ... Flag used to spawn various human corpses during the mapgen. +- `DANGEROUS` ... NPCs will not accept this item. Explosion iuse actor implies this flag. Implies + "NPC_THROW_NOW". +- `DETERGENT` ... This item can be used as a detergent in a washing machine. +- `DURABLE_MELEE` ... Item is made to hit stuff and it does it well, so it's considered to be a lot + tougher than other weapons made of the same materials. +- `FAKE_MILL` ... Item is a fake item, to denote a partially milled product by @ref + Item::process_fake_mill, where conditions for its removal are set. +- `FAKE_SMOKE` ... Item is a fake item generating smoke, recognizable by @ref + item::process_fake_smoke, where conditions for its removal are set. +- `FIREWOOD` ... This item can serve as a firewood. Items with this flag are sorted out to "Loot: + Wood" zone +- `FRAGILE_MELEE` ... Fragile items that fall apart easily when used as a weapon due to poor + construction quality and will break into components when broken. +- `GAS_DISCOUNT` ... Discount cards for the automated gas stations. +- `IS_PET_ARMOR` ... Is armor for a pet monster, not armor for a person +- `LEAK_ALWAYS` ... Leaks (may be combined with "RADIOACTIVE"). +- `LEAK_DAM` ... Leaks when damaged (may be combined with "RADIOACTIVE"). +- `NEEDS_UNFOLD` ... Has an additional time penalty upon wielding. For melee weapons and guns this + is offset by the relevant skill. Stacks with "SLOW_WIELD". +- `NO_PACKED` ... This item is not protected against contamination and won't stay sterile. Only + applies to CBMs. +- `NO_REPAIR` ... Prevents repairing of this item even if otherwise suitable tools exist. +- `NO_SALVAGE` ... Item cannot be broken down through a salvage process. Best used when something + should not be able to be broken down (i.e. base components like leather patches). +- `NO_STERILE` ... This item is not sterile. Only applies to CBMs. +- `NPC_ACTIVATE` ... NPCs can activate this item as an alternative attack. Currently by throwing it + right after activation. Implied by "BOMB". +- `NPC_ALT_ATTACK` ... Shouldn't be set directly. Implied by "NPC_ACTIVATE" and "NPC_THROWN". +- `NPC_THROWN` ... NPCs will throw this item (without activating it first) as an alternative attack. +- `NPC_THROW_NOW` ... NPCs will try to throw this item away, preferably at enemies. Implies + "TRADER_AVOID" and "NPC_THROWN". +- `PSEUDO` ... Used internally to mark items that are referred to in the crafting inventory but are + not actually items. They can be used as tools, but not as components. Implies "TRADER_AVOID". +- `RADIOACTIVE` ... Is radioactive (can be used with LEAK_*). +- `RAIN_PROTECT` ... Protects from sunlight and from rain, when wielded. +- `REDUCED_BASHING` ... Gunmod flag; reduces the item's bashing damage by 50%. +- `REDUCED_WEIGHT` ... Gunmod flag; reduces the item's base weight by 25%. +- `REQUIRES_TINDER` ... Requires tinder to be present on the tile this item tries to start a fire + on. +- `SLEEP_AID` ... This item helps in sleeping. +- `SLEEP_IGNORE` ... This item is not shown as before-sleep warning. +- `SLOW_WIELD` ... Has an additional time penalty upon wielding. For melee weapons and guns this is + offset by the relevant skill. Stacks with "NEEDS_UNFOLD". +- `TACK` ... Item can be used as tack for a mount. +- `TIE_UP` ... Item can be used to tie up a creature. +- `TINDER` ... This item can be used as tinder for lighting a fire with a REQUIRES_TINDER flagged + firestarter. +- `TRADER_AVOID` ... NPCs will not start with this item. Use this for active items (e.g. flashlight + (on)), dangerous items (e.g. active bomb), fake item or unusual items (e.g. unique quest item). +- `UNBREAKABLE_MELEE` ... Does never get damaged when used as melee weapon. +- `UNRECOVERABLE` ... Cannot be recovered from a disassembly. ## Guns -- ```BACKBLAST``` Causes a small explosion behind the person firing the weapon. Currently not implemented? -- ```BIPOD``` Handling bonus only applies on MOUNTABLE map/vehicle tiles. Does not include wield time penalty (see SLOW_WIELD). -- ```CHARGE``` Has to be charged to fire. Higher charges do more damage. -- ```COLLAPSIBLE_STOCK``` Reduces weapon volume proportional to the base size of the gun (excluding any mods). Does not include wield time penalty (see NEEDS_UNFOLD). -- ```CONSUMABLE``` Makes a gunpart have a chance to get damaged depending on ammo fired, and definable fields 'consume_chance' and 'consume_divisor'. -- ```CROSSBOW``` Counts as a crossbow for the purpose of gunmod compatibility. Default behavior is to match the skill used by that weapon. -- ```DISABLE_SIGHTS``` Prevents use of the base weapon sights -- ```FIRE_100``` Uses 100 shots per firing. -- ```FIRE_50``` Uses 50 shots per firing. -- ```FIRE_TWOHAND``` Gun can only be fired if player has two free hands. -- ```IRREMOVABLE``` Makes so that the gunmod cannot be removed. -- ```MECH_BAT``` This is an exotic battery designed to power military mechs. -- ```MOUNTED_GUN``` Gun can only be used on terrain / furniture with the "MOUNTABLE" flag, if you're a normal human. If you're an oversized mutant (Inconveniently Large, Large, Freakishly Huge, Huge), you can fire it regularly in exchange for dispersion and recoil penalties. -- ```NEVER_JAMS``` Never malfunctions. -- ```NO_UNLOAD``` Cannot be unloaded. -- ```PRIMITIVE_RANGED_WEAPON``` Allows using non-gunsmith tools to repair it (but not reinforce). -- ```PUMP_ACTION``` Gun has a rails on its pump action, allowing to install only mods with PUMP_RAIL_COMPATIBLE flag on underbarrel slot. -- ```PUMP_RAIL_COMPATIBLE``` Mod can be installed on underbarrel slot of guns with rails on their pump action. -- ```RELOAD_AND_SHOOT``` Firing automatically reloads and then shoots. -- ```RELOAD_EJECT``` Ejects shell from gun on reload instead of when fired. -- ```RELOAD_ONE``` Only reloads one round at a time. -- ```STR_DRAW``` If the weapon also has a strength requirement, lacking the requirement will penalize damage, range, and dispersion until you're unable to fire if below 50% the listed strength, instead of being a strict limit like it normally would be. -- ```STR_RELOAD``` Reload speed is affected by strength. -- ```UNDERWATER_GUN``` Gun is optimized for usage underwater, does perform badly outside of water. -- ```WATERPROOF_GUN``` Gun does not rust and can be used underwater. +- `BACKBLAST` Causes a small explosion behind the person firing the weapon. Currently not + implemented? +- `BIPOD` Handling bonus only applies on MOUNTABLE map/vehicle tiles. Does not include wield time + penalty (see SLOW_WIELD). +- `CHARGE` Has to be charged to fire. Higher charges do more damage. +- `COLLAPSIBLE_STOCK` Reduces weapon volume proportional to the base size of the gun (excluding any + mods). Does not include wield time penalty (see NEEDS_UNFOLD). +- `CONSUMABLE` Makes a gunpart have a chance to get damaged depending on ammo fired, and definable + fields 'consume_chance' and 'consume_divisor'. +- `CROSSBOW` Counts as a crossbow for the purpose of gunmod compatibility. Default behavior is to + match the skill used by that weapon. +- `DISABLE_SIGHTS` Prevents use of the base weapon sights +- `FIRE_100` Uses 100 shots per firing. +- `FIRE_50` Uses 50 shots per firing. +- `FIRE_TWOHAND` Gun can only be fired if player has two free hands. +- `IRREMOVABLE` Makes so that the gunmod cannot be removed. +- `MECH_BAT` This is an exotic battery designed to power military mechs. +- `MOUNTED_GUN` Gun can only be used on terrain / furniture with the "MOUNTABLE" flag, if you're a + normal human. If you're an oversized mutant (Inconveniently Large, Large, Freakishly Huge, Huge), + you can fire it regularly in exchange for dispersion and recoil penalties. +- `NEVER_JAMS` Never malfunctions. +- `NO_UNLOAD` Cannot be unloaded. +- `PRIMITIVE_RANGED_WEAPON` Allows using non-gunsmith tools to repair it (but not reinforce). +- `PUMP_ACTION` Gun has a rails on its pump action, allowing to install only mods with + PUMP_RAIL_COMPATIBLE flag on underbarrel slot. +- `PUMP_RAIL_COMPATIBLE` Mod can be installed on underbarrel slot of guns with rails on their pump + action. +- `RELOAD_AND_SHOOT` Firing automatically reloads and then shoots. +- `RELOAD_EJECT` Ejects shell from gun on reload instead of when fired. +- `RELOAD_ONE` Only reloads one round at a time. +- `STR_DRAW` If the weapon also has a strength requirement, lacking the requirement will penalize + damage, range, and dispersion until you're unable to fire if below 50% the listed strength, + instead of being a strict limit like it normally would be. +- `STR_RELOAD` Reload speed is affected by strength. +- `UNDERWATER_GUN` Gun is optimized for usage underwater, does perform badly outside of water. +- `WATERPROOF_GUN` Gun does not rust and can be used underwater. ### Firing modes -- ```MELEE``` Melee attack using properties of the gun or auxiliary gunmod -- ```NPC_AVOID``` NPC's will not attempt to use this mode -- ```SIMULTANEOUS``` All rounds fired concurrently (not sequentially) with recoil added only once (at the end) +- `MELEE` Melee attack using properties of the gun or auxiliary gunmod +- `NPC_AVOID` NPC's will not attempt to use this mode +- `SIMULTANEOUS` All rounds fired concurrently (not sequentially) with recoil added only once (at + the end) ### Faults #### Flags -- ```SILENT``` Makes the "faulty " text NOT appear next to item on general UI. Otherwise the fault works the same. +- `SILENT` Makes the "faulty " text NOT appear next to item on general UI. Otherwise the fault works + the same. #### Parameters -- ```turns_into``` Causes this fault to apply to the item just mended. -- ```also_mends``` Causes this fault to be mended (in addition to fault selected) once that fault is mended. - +- `turns_into` Causes this fault to apply to the item just mended. +- `also_mends` Causes this fault to be mended (in addition to fault selected) once that fault is + mended. ## Magazines -- ```MAG_BULKY``` Can be stashed in an appropriate oversize ammo pouch (intended for bulky or awkwardly shaped magazines) -- ```MAG_COMPACT``` Can be stashed in an appropriate ammo pouch (intended for compact magazines) -- ```MAG_DESTROY``` Magazine is destroyed when the last round is consumed (intended for ammo belts). Has precedence over MAG_EJECT. -- ```MAG_EJECT``` Magazine is ejected from the gun/tool when the last round is consumed -- ```SPEEDLOADER``` Acts like a magazine, except it transfers rounds to the target gun instead of being inserted into it. - +- `MAG_BULKY` Can be stashed in an appropriate oversize ammo pouch (intended for bulky or awkwardly + shaped magazines) +- `MAG_COMPACT` Can be stashed in an appropriate ammo pouch (intended for compact magazines) +- `MAG_DESTROY` Magazine is destroyed when the last round is consumed (intended for ammo belts). Has + precedence over MAG_EJECT. +- `MAG_EJECT` Magazine is ejected from the gun/tool when the last round is consumed +- `SPEEDLOADER` Acts like a magazine, except it transfers rounds to the target gun instead of being + inserted into it. ## MAP SPECIALS -- ```mx_bandits_block``` ... Road block made by bandits from tree logs. -- ```mx_burned_ground``` ... Fire has ravaged this place. -- ```mx_point_burned_ground``` ... Fire has ravaged this place. (partial application) -- ```mx_casings``` ... Several types of spent casings (solitary, groups, entire overmap tile) -- ```mx_clay_deposit``` ... A small surface clay deposit. -- ```mx_clearcut``` ... All trees become stumps. -- ```mx_collegekids``` ... Corpses and items. -- ```mx_corpses``` ... Up to 5 corpses with everyday loot. -- ```mx_crater``` ... Crater with rubble (and radioactivity). -- ```mx_drugdeal``` ... Corpses and some drugs. -- ```mx_dead_vegetation``` ... Kills all plants. (aftermath of acid rain etc.) -- ```mx_point_dead_vegetation``` ... Kills all plants. (aftermath of acid rain etc.) (partial application) -- ```mx_grove``` ... All trees and shrubs become a single species of tree. -- ```mx_grave``` ... A grave in the open field, with a corpse and some everyday loot. -- ```mx_helicopter``` ... Metal wreckage and some items. -- ```mx_jabberwock``` ... A *chance* of a jabberwock. -- ```mx_looters``` ... Up to 5 bandits spawn in the building. -- ```mx_marloss_pilgrimage``` A sect of people worshiping fungaloids. -- ```mx_mayhem``` ... Several types of road mayhem (firefights, crashed cars etc). -- ```mx_military``` ... Corpses and some military items. -- ```mx_minefield``` ... A military roadblock at the entry of the bridges with landmines scattered in the front of it. -- ```mx_null``` ... No special at all. -- ```mx_pond``` ... A small pond. -- ```mx_portal_in``` ... Another portal to neither space. -- ```mx_portal``` ... Portal to neither space, with several types of surrounding environment. -- ```mx_roadblock``` ... Roadblock furniture with turrets and some cars. -- ```mx_roadworks``` ... Partially closed damaged road with chance of work equipment and utility vehicles. -- ```mx_science``` ... Corpses and some scientist items. -- ```mx_shia``` ... A *chance* of Shia, if Crazy Catalcysm is enabled. -- ```mx_shrubbery``` ... All trees and shrubs become a single species of shrub. -- ```mx_spider``` ... A big spider web, complete with spiders and eggs. -- ```mx_supplydrop``` ... Crates with some military items in it. - +- `mx_bandits_block` ... Road block made by bandits from tree logs. +- `mx_burned_ground` ... Fire has ravaged this place. +- `mx_point_burned_ground` ... Fire has ravaged this place. (partial application) +- `mx_casings` ... Several types of spent casings (solitary, groups, entire overmap tile) +- `mx_clay_deposit` ... A small surface clay deposit. +- `mx_clearcut` ... All trees become stumps. +- `mx_collegekids` ... Corpses and items. +- `mx_corpses` ... Up to 5 corpses with everyday loot. +- `mx_crater` ... Crater with rubble (and radioactivity). +- `mx_drugdeal` ... Corpses and some drugs. +- `mx_dead_vegetation` ... Kills all plants. (aftermath of acid rain etc.) +- `mx_point_dead_vegetation` ... Kills all plants. (aftermath of acid rain etc.) (partial + application) +- `mx_grove` ... All trees and shrubs become a single species of tree. +- `mx_grave` ... A grave in the open field, with a corpse and some everyday loot. +- `mx_helicopter` ... Metal wreckage and some items. +- `mx_jabberwock` ... A _chance_ of a jabberwock. +- `mx_looters` ... Up to 5 bandits spawn in the building. +- `mx_marloss_pilgrimage` A sect of people worshiping fungaloids. +- `mx_mayhem` ... Several types of road mayhem (firefights, crashed cars etc). +- `mx_military` ... Corpses and some military items. +- `mx_minefield` ... A military roadblock at the entry of the bridges with landmines scattered in + the front of it. +- `mx_null` ... No special at all. +- `mx_pond` ... A small pond. +- `mx_portal_in` ... Another portal to neither space. +- `mx_portal` ... Portal to neither space, with several types of surrounding environment. +- `mx_roadblock` ... Roadblock furniture with turrets and some cars. +- `mx_roadworks` ... Partially closed damaged road with chance of work equipment and utility + vehicles. +- `mx_science` ... Corpses and some scientist items. +- `mx_shia` ... A _chance_ of Shia, if Crazy Catalcysm is enabled. +- `mx_shrubbery` ... All trees and shrubs become a single species of shrub. +- `mx_spider` ... A big spider web, complete with spiders and eggs. +- `mx_supplydrop` ... Crates with some military items in it. ## Material Phases -- ```GAS``` -- ```LIQUID``` -- ```NULL``` -- ```PLASMA``` -- ```SOLID``` - +- `GAS` +- `LIQUID` +- `NULL` +- `PLASMA` +- `SOLID` ## Melee ### Flags -- ```ALWAYS_TWOHAND``` Item is always wielded with two hands. Without this, the items volume and weight are used to calculate this. -- ```DIAMOND``` Diamond coating adds 30% bonus to cutting and piercing damage -- ```MESSY``` Creates more mess when pulping -- ```NO_CVD``` Item can never be used with a CVD machine -- ```NO_RELOAD``` Item can never be reloaded (even if has a valid ammo type). -- ```NO_UNWIELD``` Cannot unwield this item. -- ```POLEARM``` Item is clumsy up close and does 70% of normal damage against adjacent targets. Should be paired with REACH_ATTACK. Simple reach piercing weapons like spears should not get this flag. -- ```REACH_ATTACK``` Allows to perform reach attack. -- ```SHEATH_KNIFE``` Item can be sheathed in a knife sheath, it applicable to small/medium knives (with volume not bigger than 2) -- ```SHEATH_SWORD``` Item can be sheathed in a sword scabbard -- ```SPEAR``` When making reach attacks intervening THIN_OBSTACLE terrain is not an obstacle. Should be paired with REACH_ATTACK. -- ```UNARMED_WEAPON``` Wielding this item still counts as unarmed combat. -- ```WHIP``` Has a chance of disarming the opponent. - +- `ALWAYS_TWOHAND` Item is always wielded with two hands. Without this, the items volume and weight + are used to calculate this. +- `DIAMOND` Diamond coating adds 30% bonus to cutting and piercing damage +- `MESSY` Creates more mess when pulping +- `NO_CVD` Item can never be used with a CVD machine +- `NO_RELOAD` Item can never be reloaded (even if has a valid ammo type). +- `NO_UNWIELD` Cannot unwield this item. +- `POLEARM` Item is clumsy up close and does 70% of normal damage against adjacent targets. Should + be paired with REACH_ATTACK. Simple reach piercing weapons like spears should not get this flag. +- `REACH_ATTACK` Allows to perform reach attack. +- `SHEATH_KNIFE` Item can be sheathed in a knife sheath, it applicable to small/medium knives (with + volume not bigger than 2) +- `SHEATH_SWORD` Item can be sheathed in a sword scabbard +- `SPEAR` When making reach attacks intervening THIN_OBSTACLE terrain is not an obstacle. Should be + paired with REACH_ATTACK. +- `UNARMED_WEAPON` Wielding this item still counts as unarmed combat. +- `WHIP` Has a chance of disarming the opponent. ## Monster Groups @@ -831,22 +952,23 @@ The condition flags limit when monsters can spawn. ### Seasons -Multiple season conditions will be combined together so that any of those conditions become valid time of year spawn times. +Multiple season conditions will be combined together so that any of those conditions become valid +time of year spawn times. -- ```AUTUMN``` -- ```SPRING``` -- ```SUMMER``` -- ```WINTER``` +- `AUTUMN` +- `SPRING` +- `SUMMER` +- `WINTER` ### Time of day -Multiple time of day conditions will be combined together so that any of those conditions become valid time of day spawn times. - -- ```DAWN``` -- ```DAY``` -- ```DUSK``` -- ```NIGHT``` +Multiple time of day conditions will be combined together so that any of those conditions become +valid time of day spawn times. +- `DAWN` +- `DAY` +- `DUSK` +- `NIGHT` ## Monsters @@ -854,406 +976,430 @@ Flags used to describe monsters and define their properties and abilities. ### Anger, Fear and Placation Triggers -- ```FIRE``` There's a fire nearby. -- ```FRIEND_ATTACKED``` A monster of the same type was attacked. -- ```FRIEND_DIED``` A monster of the same type died. -- ```HURT``` The monster is hurt. -- ```MEAT``` Meat or a corpse is nearby. -- ```NULL``` Source use only? -- ```PLAYER_CLOSE``` The player gets within a few tiles distance. -- ```PLAYER_WEAK``` The player is hurt. -- ```SOUND``` Heard a sound. -- ```STALK``` Increases when following the player. +- `FIRE` There's a fire nearby. +- `FRIEND_ATTACKED` A monster of the same type was attacked. +- `FRIEND_DIED` A monster of the same type died. +- `HURT` The monster is hurt. +- `MEAT` Meat or a corpse is nearby. +- `NULL` Source use only? +- `PLAYER_CLOSE` The player gets within a few tiles distance. +- `PLAYER_WEAK` The player is hurt. +- `SOUND` Heard a sound. +- `STALK` Increases when following the player. ### Categories -- ```CLASSIC``` Only monsters we expect in a classic zombie movie. -- ```NULL``` No category. -- ```WILDLIFE``` Natural animals. +- `CLASSIC` Only monsters we expect in a classic zombie movie. +- `NULL` No category. +- `WILDLIFE` Natural animals. ### Death Functions Multiple death functions can be used. Not all combinations make sense. -- ```ACID``` Acid instead of a body. not the same as the ACID_BLOOD flag. In most cases you want both. -- ```AMIGARA``` Removes hypnosis if the last one. -- ```BLOBSPLIT``` Creates more blobs. -- ```BOOMER``` Explodes in vomit. -- ```BROKEN``` Spawns a broken robot item, its id calculated like this: the prefix "mon_" is removed from the monster id, than the prefix "broken_" is added. Example: mon_eyebot -> broken_eyebot -- ```DISAPPEAR``` Hallucination disappears. -- ```DISINTEGRATE``` Falls apart. -- ```EXPLODE``` Damaging explosion. -- ```FIREBALL``` 10 percent chance to explode in a fireball. -- ```FLAME_EXPLOSION``` guaranteed to explode and starts fires. -- ```FUNGUS``` Explodes in spores. -- ```GAMEOVER``` Game over man! Game over! Defense mode. -- ```GUILT``` Moral penalty. There is also a flag with a similar effect. -- ```KILL_BREATHERS``` All breathers die. -- ```KILL_VINES``` Kill all nearby vines. -- ```MELT``` Normal death, but melts. -- ```NORMAL``` Drop a body, leave gibs. -- ```RATKING``` Cure verminitis. -- ```SMOKEBURST``` Explode like a huge smoke bomb. -- ```THING``` Turn into a full thing. -- ```TRIFFID_HEART``` Destroys all roots. -- ```VINE_CUT``` Kill adjacent vine if it's cut. -- ```WORM``` Spawns 2 half-worms +- `ACID` Acid instead of a body. not the same as the ACID_BLOOD flag. In most cases you want both. +- `AMIGARA` Removes hypnosis if the last one. +- `BLOBSPLIT` Creates more blobs. +- `BOOMER` Explodes in vomit. +- `BROKEN` Spawns a broken robot item, its id calculated like this: the prefix "mon_" is removed + from the monster id, than the prefix "broken_" is added. Example: mon_eyebot -> broken_eyebot +- `DISAPPEAR` Hallucination disappears. +- `DISINTEGRATE` Falls apart. +- `EXPLODE` Damaging explosion. +- `FIREBALL` 10 percent chance to explode in a fireball. +- `FLAME_EXPLOSION` guaranteed to explode and starts fires. +- `FUNGUS` Explodes in spores. +- `GAMEOVER` Game over man! Game over! Defense mode. +- `GUILT` Moral penalty. There is also a flag with a similar effect. +- `KILL_BREATHERS` All breathers die. +- `KILL_VINES` Kill all nearby vines. +- `MELT` Normal death, but melts. +- `NORMAL` Drop a body, leave gibs. +- `RATKING` Cure verminitis. +- `SMOKEBURST` Explode like a huge smoke bomb. +- `THING` Turn into a full thing. +- `TRIFFID_HEART` Destroys all roots. +- `VINE_CUT` Kill adjacent vine if it's cut. +- `WORM` Spawns 2 half-worms ### Flags -- ```ABSORBS_SPLITS``` Consumes objects it moves over, and if it absorbs enough it will split into a copy. -- ```ABSORBS``` Consumes objects it moves over. (Modders use this). -- ```ACIDPROOF``` Immune to acid. -- ```ACIDTRAIL``` Leaves a trail of acid. -- ```ACID_BLOOD``` Makes monster bleed acid. Fun stuff! Does not automatically dissolve in a pool of acid on death. -- ```ANIMAL``` Is an _animal_ for purposes of the `Animal Empathy` trait. -- ```AQUATIC``` Confined to water. -- ```ARTHROPOD_BLOOD``` Forces monster to bleed hemolymph. -- ```ATTACKMON``` Attacks other monsters. -- ```BADVENOM``` Attack may **severely** poison the player. -- ```BASHES``` Bashes down doors. -- ```BILE_BLOOD``` Makes monster bleed bile. -- ```BIRDFOOD``` Becomes friendly / tamed with bird food. -- ```BLEED``` Causes the player to bleed. -- ```BONES``` May produce bones and sinews when butchered. -- ```BORES``` Tunnels through just about anything (15x bash multiplier: dark wyrms' bash skill 12->180) -- ```CAN_DIG``` Can dig _and_ walk. -- ```CAN_OPEN_DOORS``` Can open doors on its path. -- ```CANPLAY``` This creature can be played with if it's a pet. -- ```CATFOOD``` Becomes friendly / tamed with cat food. -- ```CATTLEFODDER``` Becomes friendly / tamed with cattle fodder. -- ```CBM_CIV``` May produce a common CBM a power CBM when butchered. -- ```CBM_OP``` May produce a CBM or two from 'bionics_op' item group when butchered. -- ```CBM_POWER``` May produce a power CBM when butchered, independent of CBM. -- ```CBM_SCI``` May produce a CBM from 'bionics_sci' item group when butchered. -- ```CBM_SUBS``` May produce a CBM or two from bionics_subs and a power CBM when butchered. -- ```CBM_TECH``` May produce a CBM or two from 'bionics_tech' item group and a power CBM when butchered. -- ```CHITIN``` May produce chitin when butchered. -- ```CLIMBS``` Can climb. -- ```COLDROOF``` Immune to cold damage. -- ```CURRENT``` this water is flowing. -- ```DESTROYS``` Bashes down walls and more. (2.5x bash multiplier, where base is the critter's max melee bashing) -- ```DIGS``` Digs through the ground. -- ```DOGFOOD``` Becomes friendly / tamed with dog food. -- ```DRIPS_GASOLINE``` Occasionally drips gasoline on move. -- ```DRIPS_NAPALM``` Occasionally drips napalm on move. -- ```ELECTRIC``` Shocks unarmed attackers. -- ```ELECTRONIC``` e.g. A Robot; affected by emp blasts and other stuff. -- ```FAT``` May produce fat when butchered. -- ```FEATHER``` May produce feathers when butchered. -- ```FILTHY``` Any clothing it drops will be filthy. -- ```FIREPROOF``` Immune to fire. -- ```FIREY``` Burns stuff and is immune to fire. -- ```FISHABLE``` It is fishable. -- ```FLAMMABLE``` Monster catches fire, burns, and spreads fire to nearby objects. -- ```FLIES``` Can fly (over water, etc.) -- ```FUR``` May produce fur when butchered. -- ```GOODHEARING``` Pursues sounds more than most monsters. -- ```GRABS``` Its attacks may grab you! -- ```GROUP_BASH``` Gets help from monsters around it when bashing. -- ```GROUP_MORALE``` More courageous when near friends. -- ```GUILT``` You feel guilty for killing it. -- ```HARDTOSHOOT``` It's one size smaller for ranged attacks, no less then MS_TINY -- ```HEARS``` It can hear you. -- ```HIT_AND_RUN``` Flee for several turns after a melee attack. -- ```HUMAN``` It's a live human, as long as it's alive. -- ```CONSOLE_DESPAWN``` Despawns when a nearby console is properly hacked. -- ```IMMOBILE``` Doesn't move (e.g. turrets) -- ```ID_CARD_DESPAWN``` Despawns when a science ID card is used on a nearby console -- ```INTERIOR_AMMO``` Monster contains ammo inside itself, no need to load on launch. Prevents ammo from being dropped on disable. -- ```KEENNOSE``` Keen sense of smell. -- ```LARVA``` Creature is a larva. Currently used for gib and blood handling. -- ```LEATHER``` May produce leather when butchered. -- ```LOUDMOVES``` Mkes move noises as if ~2 sizes louder, even if flying. -- ```MECH_RECON_VISION``` This mech grants you night-vision and enhanced overmap sight radius when piloted. -- ```MECH_DEFENSIVE``` This mech can protect you thoroughly when piloted. -- ```MILITARY_MECH``` Is a military-grade mech. -- ```MILKABLE``` Produces milk when milked. -- ```NIGHT_INVISIBILITY``` Monster becomes invisible if it's more than one tile away and the lighting on its tile is LL_LOW or less. Visibility is not affected by night vision. -- ```NOGIB``` Does not leave gibs / meat chunks when killed with huge damage. -- ```NOHEAD``` Headshots not allowed! -- ```NO_BREATHE``` Creature can't drown and is unharmed by gas, smoke or poison. -- ```NO_BREED``` Creature doesn't reproduce even though it has reproduction data - useful when using copy-from to make child versions of adult creatures -- ```NO_FUNG_DMG``` Creature is immune to fungal spores and can't be fungalized. -- ```PAY_BOT``` Creature can be turned into a pet for a limited time in exchange of e-money. -- ```PET_MOUNTABLE``` Creature can be ridden or attached to an harness. -- ```PET_HARNESSABLE```Creature can be attached to an harness. -- ```NULL``` Source use only. -- ```PACIFIST``` That monster will never do melee attacks. -- ```PARALYZE``` Attack may paralyze the player with venom. -- ```PLASTIC``` Absorbs physical damage to a great degree. -- ```POISON``` Poisonous to eat. -- ```PUSH_MON``` Can push creatures out of its way. -- ```QUEEN``` When it dies, local populations start to die off too. -- ```REVIVES``` Monster corpse will revive after a short period of time. -- ```RIDEABLE_MECH``` This monster is a mech suit that can be piloted. -- ```SEES``` It can see you (and will run/follow). -- ```SHEARABLE``` This monster can be sheared for wool. -- ```SLUDGEPROOF``` Ignores the effect of sludge trails. -- ```SLUDGETRAIL``` Causes the monster to leave a sludge trap trail when moving. -- ```SMELLS``` It can smell you. -- ```STUMBLES``` Stumbles in its movement. -- ```SUNDEATH``` Dies in full sunlight. -- ```SWARMS``` Groups together and form loose packs. -- ```SWIMS``` Treats water as 50 movement point terrain. -- ```VENOM``` Attack may poison the player. -- ```VERMIN``` Obsolete flag for inconsequential monsters, now prevents loading. -- ```WARM``` Warm blooded. -- ```WEBWALK``` Doesn't destroy webs. -- ```WOOL``` May produce wool when butchered. +- `ABSORBS_SPLITS` Consumes objects it moves over, and if it absorbs enough it will split into a + copy. +- `ABSORBS` Consumes objects it moves over. (Modders use this). +- `ACIDPROOF` Immune to acid. +- `ACIDTRAIL` Leaves a trail of acid. +- `ACID_BLOOD` Makes monster bleed acid. Fun stuff! Does not automatically dissolve in a pool of + acid on death. +- `ANIMAL` Is an _animal_ for purposes of the `Animal Empathy` trait. +- `AQUATIC` Confined to water. +- `ARTHROPOD_BLOOD` Forces monster to bleed hemolymph. +- `ATTACKMON` Attacks other monsters. +- `BADVENOM` Attack may **severely** poison the player. +- `BASHES` Bashes down doors. +- `BILE_BLOOD` Makes monster bleed bile. +- `BIRDFOOD` Becomes friendly / tamed with bird food. +- `BLEED` Causes the player to bleed. +- `BONES` May produce bones and sinews when butchered. +- `BORES` Tunnels through just about anything (15x bash multiplier: dark wyrms' bash skill 12->180) +- `CAN_DIG` Can dig _and_ walk. +- `CAN_OPEN_DOORS` Can open doors on its path. +- `CANPLAY` This creature can be played with if it's a pet. +- `CATFOOD` Becomes friendly / tamed with cat food. +- `CATTLEFODDER` Becomes friendly / tamed with cattle fodder. +- `CBM_CIV` May produce a common CBM a power CBM when butchered. +- `CBM_OP` May produce a CBM or two from 'bionics_op' item group when butchered. +- `CBM_POWER` May produce a power CBM when butchered, independent of CBM. +- `CBM_SCI` May produce a CBM from 'bionics_sci' item group when butchered. +- `CBM_SUBS` May produce a CBM or two from bionics_subs and a power CBM when butchered. +- `CBM_TECH` May produce a CBM or two from 'bionics_tech' item group and a power CBM when butchered. +- `CHITIN` May produce chitin when butchered. +- `CLIMBS` Can climb. +- `COLDROOF` Immune to cold damage. +- `CURRENT` this water is flowing. +- `DESTROYS` Bashes down walls and more. (2.5x bash multiplier, where base is the critter's max + melee bashing) +- `DIGS` Digs through the ground. +- `DOGFOOD` Becomes friendly / tamed with dog food. +- `DRIPS_GASOLINE` Occasionally drips gasoline on move. +- `DRIPS_NAPALM` Occasionally drips napalm on move. +- `ELECTRIC` Shocks unarmed attackers. +- `ELECTRONIC` e.g. A Robot; affected by emp blasts and other stuff. +- `FAT` May produce fat when butchered. +- `FEATHER` May produce feathers when butchered. +- `FILTHY` Any clothing it drops will be filthy. +- `FIREPROOF` Immune to fire. +- `FIREY` Burns stuff and is immune to fire. +- `FISHABLE` It is fishable. +- `FLAMMABLE` Monster catches fire, burns, and spreads fire to nearby objects. +- `FLIES` Can fly (over water, etc.) +- `FUR` May produce fur when butchered. +- `GOODHEARING` Pursues sounds more than most monsters. +- `GRABS` Its attacks may grab you! +- `GROUP_BASH` Gets help from monsters around it when bashing. +- `GROUP_MORALE` More courageous when near friends. +- `GUILT` You feel guilty for killing it. +- `HARDTOSHOOT` It's one size smaller for ranged attacks, no less then MS_TINY +- `HEARS` It can hear you. +- `HIT_AND_RUN` Flee for several turns after a melee attack. +- `HUMAN` It's a live human, as long as it's alive. +- `CONSOLE_DESPAWN` Despawns when a nearby console is properly hacked. +- `IMMOBILE` Doesn't move (e.g. turrets) +- `ID_CARD_DESPAWN` Despawns when a science ID card is used on a nearby console +- `INTERIOR_AMMO` Monster contains ammo inside itself, no need to load on launch. Prevents ammo from + being dropped on disable. +- `KEENNOSE` Keen sense of smell. +- `LARVA` Creature is a larva. Currently used for gib and blood handling. +- `LEATHER` May produce leather when butchered. +- `LOUDMOVES` Mkes move noises as if ~2 sizes louder, even if flying. +- `MECH_RECON_VISION` This mech grants you night-vision and enhanced overmap sight radius when + piloted. +- `MECH_DEFENSIVE` This mech can protect you thoroughly when piloted. +- `MILITARY_MECH` Is a military-grade mech. +- `MILKABLE` Produces milk when milked. +- `NIGHT_INVISIBILITY` Monster becomes invisible if it's more than one tile away and the lighting on + its tile is LL_LOW or less. Visibility is not affected by night vision. +- `NOGIB` Does not leave gibs / meat chunks when killed with huge damage. +- `NOHEAD` Headshots not allowed! +- `NO_BREATHE` Creature can't drown and is unharmed by gas, smoke or poison. +- `NO_BREED` Creature doesn't reproduce even though it has reproduction data - useful when using + copy-from to make child versions of adult creatures +- `NO_FUNG_DMG` Creature is immune to fungal spores and can't be fungalized. +- `PAY_BOT` Creature can be turned into a pet for a limited time in exchange of e-money. +- `PET_MOUNTABLE` Creature can be ridden or attached to an harness. +- `PET_HARNESSABLE`Creature can be attached to an harness. +- `NULL` Source use only. +- `PACIFIST` That monster will never do melee attacks. +- `PARALYZE` Attack may paralyze the player with venom. +- `PLASTIC` Absorbs physical damage to a great degree. +- `POISON` Poisonous to eat. +- `PUSH_MON` Can push creatures out of its way. +- `QUEEN` When it dies, local populations start to die off too. +- `REVIVES` Monster corpse will revive after a short period of time. +- `RIDEABLE_MECH` This monster is a mech suit that can be piloted. +- `SEES` It can see you (and will run/follow). +- `SHEARABLE` This monster can be sheared for wool. +- `SLUDGEPROOF` Ignores the effect of sludge trails. +- `SLUDGETRAIL` Causes the monster to leave a sludge trap trail when moving. +- `SMELLS` It can smell you. +- `STUMBLES` Stumbles in its movement. +- `SUNDEATH` Dies in full sunlight. +- `SWARMS` Groups together and form loose packs. +- `SWIMS` Treats water as 50 movement point terrain. +- `VENOM` Attack may poison the player. +- `VERMIN` Obsolete flag for inconsequential monsters, now prevents loading. +- `WARM` Warm blooded. +- `WEBWALK` Doesn't destroy webs. +- `WOOL` May produce wool when butchered. ### Monster Defense and Attacks -- ```ACIDSPLASH``` Splash acid on the attacker -- ```NONE``` No special attack-back -- ```ZAPBACK``` Shock attacker on hit +- `ACIDSPLASH` Splash acid on the attacker +- `NONE` No special attack-back +- `ZAPBACK` Shock attacker on hit ### Sizes -- ```HUGE``` Tank -- ```LARGE``` Cow -- ```MEDIUM``` Human -- ```SMALL``` Dog -- ```TINY``` Squirrel +- `HUGE` Tank +- `LARGE` Cow +- `MEDIUM` Human +- `SMALL` Dog +- `TINY` Squirrel ### Special attacks -Some special attacks are also valid use actions for tools and weapons. -See `monsters.json` for examples on how to use these attacks. -Also see `monster_attacks.json` for more special attacks, for example, impale and scratch. - -- ```ACID_ACCURATE``` Shoots acid that is accurate at long ranges, but less so up close. -- ```ACID_BARF``` Barfs corroding, blinding acid. -- ```ACID``` Spit acid. -- ```ANTQUEEN``` Hatches/grows: `egg > ant > soldier`. -- ```BIO_OP_BIOJUTSU``` Attack with a random special martial art maneuver. -- ```BIO_OP_TAKEDOWN``` Attack with special martial art takedown maneuver. -- ```BIO_OP_DISARM``` Attack with a special martial art disarm maneuver. -- ```BIO_OP_IMPALE``` Attack with a strong martial art maneuver. -- ```BITE``` Bite attack that can cause deep infected wounds. -- ```BMG_TUR``` Barrett .50BMG rifle fires. -- ```BOOMER_GLOW``` Spit glowing bile. -- ```BOOMER``` Spit bile. -- ```BRANDISH``` Brandish a knife at the player. -- ```BREATHE``` Spawns a `breather` -- ```CALLBLOBS``` Calls 2/3 of nearby blobs to defend this monster, and sends 1/3 of nearby blobs after the player. -- ```CHICKENBOT``` LEGACY - Robot can attack with tazer, M4, or MGL depending on distance. -- ```COPBOT``` Cop-bot alerts and then tazes the player. -- ```DANCE``` Monster dances. -- ```DARKMAN``` Can cause darkness and wraiths to spawn. -- ```DERMATIK_GROWTH``` Dermatik larva grows into an adult. -- ```DERMATIK``` Attempts to lay dermatik eggs in the player. -- ```DISAPPEAR``` Hallucination disappears. -- ```DOGTHING``` The dog _thing_ spawns into a tentacle dog. -- ```FEAR_PARALYZE``` Paralyze the player with fear. -- ```FLAMETHROWER``` Shoots a stream of fire. -- ```FLESH_GOLEM``` Attack the player with claw, and inflict disease `downed` if the attack connects. -- ```FORMBLOB``` Spawns blobs? -- ```FRAG_TUR``` MGL fires frag rounds. -- ```FUNGUS_BIG_BLOSSOM``` Spreads fire suppressing fungal haze. -- ```FUNGUS_BRISTLE``` Perform barbed tendril attack that can cause fungal infections. -- ```FUNGUS_CORPORATE``` Used solely by Crazy Cataclysm. This will cause runtime errors if used without out, and spawns SpOreos on top of the creature. -- ```FUNGUS_FORTIFY``` Grows Fungal hedgerows, and advances player on the mycus threshold path. -- ```FUNGUS_GROWTH``` Grows a young fungaloid into an adult. -- ```FUNGUS_HAZE``` Spawns fungal fields. -- ```FUNGUS_INJECT``` Perform needle attack that can cause fungal infections. -- ```FUNGUS_SPROUT``` Grows a fungal wall. -- ```FUNGUS``` Releases fungal spores and attempts to infect the player. -- ```GENERATOR``` Regenerates health. -- ```GENE_STING``` Shoot a dart at the player that causes a mutation if it connects. -- ```GRAB``` GRAB the target, and drag it around. -- ```GRAB``` Grabs the player, slowing on hit, making movement and dodging impossible and blocking harder. -- ```GROWPLANTS``` Spawns underbrush, or promotes it to `> young tree > tree`. -- ```GROW_VINE``` Grows creeper vines. -- ```HOWL``` "an ear-piercing howl!" -- ```JACKSON``` Converts zombies into zombie dancers. -- ```LASER``` Laser turret fires. -- ```LEAP``` leap away to an unobstructed tile. -- ```LONGSWIPE``` Does high damage claw attack, which can even hit some distance away. -- ```LUNGE``` Perform a jumping attack from some distance away, which can down the target. -- ```MULTI_ROBOT``` Robot can attack with tazer, flamethrower, M4, MGL, or 120mm cannon depending on distance. -- ```NONE``` No special attack. -- ```PARA_STING``` Shoot a paralyzing dart at the player. -- ```PARROT``` Parrots the speech defined in `speech.json`, picks one of the lines randomly. "speaker" points to a monster id. -- ```PARROT_AT_DANGER``` Performs the same function as PARROT, but only if the creature sees an angry monster from a hostile faction. -- ```PAID_BOT``` For creature with PAY_BOT flag, removes the ally status when the pet effect runs out. -- ```PHOTOGRAPH``` Photograph the player. Causes a robot attack? -- ```PLANT``` Fungal spores take seed and grow into a fungaloid. -- ```PULL_METAL_WEAPON``` Pull weapon that's made of iron or steel from the player's hand. -- ```RANGED_PULL``` Pull targets towards attacker. -- ```RATKING``` Inflicts disease `rat` -- ```RATTLE``` "a sibilant rattling sound!" -- ```RESURRECT``` Revives the dead--again. -- ```RIFLE_TUR``` Rifle turret fires. -- ```RIOTBOT``` Sprays teargas or relaxation gas, can handcuff players, and can use a blinding flash. -- ```SCIENCE``` Various science/technology related attacks (e.g. manhacks, radioactive beams, etc.) -- ```SEARCHLIGHT``` Tracks targets with a searchlight. -- ```SHOCKING_REVEAL``` Shoots bolts of lightning, and reveals a SHOCKING FACT! Very fourth-wall breaking. Used solely by Crazy Cataclysm. -- ```SHOCKSTORM``` Shoots bolts of lightning. -- ```SHRIEK_ALERT``` "a very terrible shriek!" -- ```SHRIEK_STUN``` "a stunning shriek!", causes a small bash, can cause a stun. -- ```SHRIEK``` "a terrible shriek!" -- ```SLIMESPRING``` Can provide a morale boost to the player, and cure bite and bleed effects. -- ```SMASH``` Smashes the target for massive damage, sending it flying for a number of tiles equal to `("melee_dice" * "melee_dice_sides" * 3) / 10`. -- ```SMG``` SMG turret fires. -- ```SPIT_SAP``` Spit sap. -- ```STARE``` Stare at the player and inflict teleglow. -- ```STRETCH_ATTACK``` Long ranged piercing attack. -- ```STRETCH_BITE``` Long ranged bite attack. -- ```SUICIDE``` Dies after attacking. -- ```TAZER``` Shock the player. -- ```TENTACLE``` Lashes a tentacle at the player. -- ```TRIFFID_GROWTH``` Young triffid grows into an adult. -- ```TRIFFID_HEARTBEAT``` Grows and crumbles root walls around the player, and spawns more monsters. -- ```UPGRADE``` Upgrades a regular zombie into a special zombie. -- ```VINE``` Attacks with vine. -- ```VORTEX``` Forms a vortex/tornado that causes damage and throws creatures around. - +Some special attacks are also valid use actions for tools and weapons. See `monsters.json` for +examples on how to use these attacks. Also see `monster_attacks.json` for more special attacks, for +example, impale and scratch. + +- `ACID_ACCURATE` Shoots acid that is accurate at long ranges, but less so up close. +- `ACID_BARF` Barfs corroding, blinding acid. +- `ACID` Spit acid. +- `ANTQUEEN` Hatches/grows: `egg > ant > soldier`. +- `BIO_OP_BIOJUTSU` Attack with a random special martial art maneuver. +- `BIO_OP_TAKEDOWN` Attack with special martial art takedown maneuver. +- `BIO_OP_DISARM` Attack with a special martial art disarm maneuver. +- `BIO_OP_IMPALE` Attack with a strong martial art maneuver. +- `BITE` Bite attack that can cause deep infected wounds. +- `BMG_TUR` Barrett .50BMG rifle fires. +- `BOOMER_GLOW` Spit glowing bile. +- `BOOMER` Spit bile. +- `BRANDISH` Brandish a knife at the player. +- `BREATHE` Spawns a `breather` +- `CALLBLOBS` Calls 2/3 of nearby blobs to defend this monster, and sends 1/3 of nearby blobs after + the player. +- `CHICKENBOT` LEGACY - Robot can attack with tazer, M4, or MGL depending on distance. +- `COPBOT` Cop-bot alerts and then tazes the player. +- `DANCE` Monster dances. +- `DARKMAN` Can cause darkness and wraiths to spawn. +- `DERMATIK_GROWTH` Dermatik larva grows into an adult. +- `DERMATIK` Attempts to lay dermatik eggs in the player. +- `DISAPPEAR` Hallucination disappears. +- `DOGTHING` The dog _thing_ spawns into a tentacle dog. +- `FEAR_PARALYZE` Paralyze the player with fear. +- `FLAMETHROWER` Shoots a stream of fire. +- `FLESH_GOLEM` Attack the player with claw, and inflict disease `downed` if the attack connects. +- `FORMBLOB` Spawns blobs? +- `FRAG_TUR` MGL fires frag rounds. +- `FUNGUS_BIG_BLOSSOM` Spreads fire suppressing fungal haze. +- `FUNGUS_BRISTLE` Perform barbed tendril attack that can cause fungal infections. +- `FUNGUS_CORPORATE` Used solely by Crazy Cataclysm. This will cause runtime errors if used without + out, and spawns SpOreos on top of the creature. +- `FUNGUS_FORTIFY` Grows Fungal hedgerows, and advances player on the mycus threshold path. +- `FUNGUS_GROWTH` Grows a young fungaloid into an adult. +- `FUNGUS_HAZE` Spawns fungal fields. +- `FUNGUS_INJECT` Perform needle attack that can cause fungal infections. +- `FUNGUS_SPROUT` Grows a fungal wall. +- `FUNGUS` Releases fungal spores and attempts to infect the player. +- `GENERATOR` Regenerates health. +- `GENE_STING` Shoot a dart at the player that causes a mutation if it connects. +- `GRAB` GRAB the target, and drag it around. +- `GRAB` Grabs the player, slowing on hit, making movement and dodging impossible and blocking + harder. +- `GROWPLANTS` Spawns underbrush, or promotes it to `> young tree > tree`. +- `GROW_VINE` Grows creeper vines. +- `HOWL` "an ear-piercing howl!" +- `JACKSON` Converts zombies into zombie dancers. +- `LASER` Laser turret fires. +- `LEAP` leap away to an unobstructed tile. +- `LONGSWIPE` Does high damage claw attack, which can even hit some distance away. +- `LUNGE` Perform a jumping attack from some distance away, which can down the target. +- `MULTI_ROBOT` Robot can attack with tazer, flamethrower, M4, MGL, or 120mm cannon depending on + distance. +- `NONE` No special attack. +- `PARA_STING` Shoot a paralyzing dart at the player. +- `PARROT` Parrots the speech defined in `speech.json`, picks one of the lines randomly. "speaker" + points to a monster id. +- `PARROT_AT_DANGER` Performs the same function as PARROT, but only if the creature sees an angry + monster from a hostile faction. +- `PAID_BOT` For creature with PAY_BOT flag, removes the ally status when the pet effect runs out. +- `PHOTOGRAPH` Photograph the player. Causes a robot attack? +- `PLANT` Fungal spores take seed and grow into a fungaloid. +- `PULL_METAL_WEAPON` Pull weapon that's made of iron or steel from the player's hand. +- `RANGED_PULL` Pull targets towards attacker. +- `RATKING` Inflicts disease `rat` +- `RATTLE` "a sibilant rattling sound!" +- `RESURRECT` Revives the dead--again. +- `RIFLE_TUR` Rifle turret fires. +- `RIOTBOT` Sprays teargas or relaxation gas, can handcuff players, and can use a blinding flash. +- `SCIENCE` Various science/technology related attacks (e.g. manhacks, radioactive beams, etc.) +- `SEARCHLIGHT` Tracks targets with a searchlight. +- `SHOCKING_REVEAL` Shoots bolts of lightning, and reveals a SHOCKING FACT! Very fourth-wall + breaking. Used solely by Crazy Cataclysm. +- `SHOCKSTORM` Shoots bolts of lightning. +- `SHRIEK_ALERT` "a very terrible shriek!" +- `SHRIEK_STUN` "a stunning shriek!", causes a small bash, can cause a stun. +- `SHRIEK` "a terrible shriek!" +- `SLIMESPRING` Can provide a morale boost to the player, and cure bite and bleed effects. +- `SMASH` Smashes the target for massive damage, sending it flying for a number of tiles equal to + `("melee_dice" * "melee_dice_sides" * 3) / 10`. +- `SMG` SMG turret fires. +- `SPIT_SAP` Spit sap. +- `STARE` Stare at the player and inflict teleglow. +- `STRETCH_ATTACK` Long ranged piercing attack. +- `STRETCH_BITE` Long ranged bite attack. +- `SUICIDE` Dies after attacking. +- `TAZER` Shock the player. +- `TENTACLE` Lashes a tentacle at the player. +- `TRIFFID_GROWTH` Young triffid grows into an adult. +- `TRIFFID_HEARTBEAT` Grows and crumbles root walls around the player, and spawns more monsters. +- `UPGRADE` Upgrades a regular zombie into a special zombie. +- `VINE` Attacks with vine. +- `VORTEX` Forms a vortex/tornado that causes damage and throws creatures around. ## Mutations #### Flags -- ```NO_RADIATION``` This mutation grants immunity to radiations. -- ```NO_THIRST``` Your thirst is not modified by food or drinks. -- ```UNARMED_BONUS``` You get a bonus to unarmed bash and cut damage equal to unarmed_skill/2 up to 4. - +- `NO_RADIATION` This mutation grants immunity to radiations. +- `NO_THIRST` Your thirst is not modified by food or drinks. +- `UNARMED_BONUS` You get a bonus to unarmed bash and cut damage equal to unarmed_skill/2 up to 4. ### Categories These branches are also the valid entries for the categories of `dreams` in `dreams.json` -- ```MUTCAT_ALPHA``` "You feel...better. Somehow." -- ```MUTCAT_BEAST``` "Your heart races and you see blood for a moment." -- ```MUTCAT_BIRD``` "Your body lightens and you long for the sky." -- ```MUTCAT_CATTLE``` "Your mind and body slow down. You feel peaceful." -- ```MUTCAT_CEPHALOPOD``` "Your mind is overcome by images of eldritch horrors...and then they pass." -- ```MUTCAT_CHIMERA``` "You need to roar, bask, bite, and flap. NOW." -- ```MUTCAT_ELFA``` "Nature is becoming one with you..." -- ```MUTCAT_FISH``` "You are overcome by an overwhelming longing for the ocean." -- ```MUTCAT_INSECT``` "You hear buzzing, and feel your body harden." -- ```MUTCAT_LIZARD``` "For a heartbeat, your body cools down." -- ```MUTCAT_MEDICAL``` "Your can feel the blood rushing through your veins and a strange, medicated feeling washes over your senses." -- ```MUTCAT_PLANT``` "You feel much closer to nature." -- ```MUTCAT_RAPTOR``` "Mmm...sweet bloody flavor...tastes like victory." -- ```MUTCAT_RAT``` "You feel a momentary nausea." -- ```MUTCAT_SLIME``` "Your body loses all rigidity for a moment." -- ```MUTCAT_SPIDER``` "You feel insidious." -- ```MUTCAT_TROGLOBITE``` "You yearn for a cool, dark place to hide." - +- `MUTCAT_ALPHA` "You feel...better. Somehow." +- `MUTCAT_BEAST` "Your heart races and you see blood for a moment." +- `MUTCAT_BIRD` "Your body lightens and you long for the sky." +- `MUTCAT_CATTLE` "Your mind and body slow down. You feel peaceful." +- `MUTCAT_CEPHALOPOD` "Your mind is overcome by images of eldritch horrors...and then they pass." +- `MUTCAT_CHIMERA` "You need to roar, bask, bite, and flap. NOW." +- `MUTCAT_ELFA` "Nature is becoming one with you..." +- `MUTCAT_FISH` "You are overcome by an overwhelming longing for the ocean." +- `MUTCAT_INSECT` "You hear buzzing, and feel your body harden." +- `MUTCAT_LIZARD` "For a heartbeat, your body cools down." +- `MUTCAT_MEDICAL` "Your can feel the blood rushing through your veins and a strange, medicated + feeling washes over your senses." +- `MUTCAT_PLANT` "You feel much closer to nature." +- `MUTCAT_RAPTOR` "Mmm...sweet bloody flavor...tastes like victory." +- `MUTCAT_RAT` "You feel a momentary nausea." +- `MUTCAT_SLIME` "Your body loses all rigidity for a moment." +- `MUTCAT_SPIDER` "You feel insidious." +- `MUTCAT_TROGLOBITE` "You yearn for a cool, dark place to hide." ## Overmap ### Overmap connections -- ```ORTHOGONAL``` The connection generally prefers straight lines, avoids turning wherever possible. +- `ORTHOGONAL` The connection generally prefers straight lines, avoids turning wherever possible. ### Overmap specials #### Flags -- ```BEE``` Location is related to bees. Used to classify location. -- ```BLOB``` Location should "blob" outward from the defined location with a chance to be placed in adjacent locations. -- ```CLASSIC``` Location is allowed when classic zombies are enabled. -- ```FUNGAL``` Location is related to fungi. Used to classify location. -- ```TRIFFID``` Location is related to triffids. Used to classify location. -- ```LAKE``` Location is is placed on a lake and will be ignored for placement if the overmap doesn't contain any lake terrain. -- ```UNIQUE``` Location is unique and will only occur once per overmap. `occurrences` is overridden to define a percent chance (e.g. `"occurrences" : [75, 100]` is 75%) +- `BEE` Location is related to bees. Used to classify location. +- `BLOB` Location should "blob" outward from the defined location with a chance to be placed in + adjacent locations. +- `CLASSIC` Location is allowed when classic zombies are enabled. +- `FUNGAL` Location is related to fungi. Used to classify location. +- `TRIFFID` Location is related to triffids. Used to classify location. +- `LAKE` Location is is placed on a lake and will be ignored for placement if the overmap doesn't + contain any lake terrain. +- `UNIQUE` Location is unique and will only occur once per overmap. `occurrences` is overridden to + define a percent chance (e.g. `"occurrences" : [75, 100]` is 75%) ### Overmap terrains #### Flags -- ```KNOWN_DOWN``` There's a known way down. -- ```KNOWN_UP``` There's a known way up. -- ```LINEAR``` For roads etc, which use ID_straight, ID_curved, ID_tee, ID_four_way. -- ```NO_ROTATE``` The terrain can't be rotated (ID_north, ID_east, ID_south, and ID_west instances will NOT be generated, just ID). -- ```RIVER``` It's a river tile. -- ```SIDEWALK``` Has sidewalks on the sides adjacent to roads. -- ```LAKE``` Consider this location to be a valid lake terrain for mapgen purposes. -- ```LAKE_SHORE``` Consider this location to be a valid lake shore terrain for mapgen purposes. -- ```SOURCE_FUEL``` For NPC AI, this location may contain fuel for looting. -- ```SOURCE_FOOD``` For NPC AI, this location may contain food for looting. -- ```SOURCE_FARMING``` For NPC AI, this location may contain useful farming supplies for looting. -- ```SOURCE_FABRICATION``` For NPC AI, this location may contain fabrication tools and components for looting. -- ```SOURCE_GUN``` For NPC AI, this location may contain guns for looting. -- ```SOURCE_AMMO``` For NPC AI, this location may contain ammo for looting. -- ```SOURCE_BOOKS``` For NPC AI, this location may contain books for looting. -- ```SOURCE_WEAPON``` For NPC AI, this location may contain weapons for looting. -- ```SOURCE_FORAGE``` For NPC AI, this location may contain plants to forage. -- ```SOURCE_COOKING``` For NPC AI, this location may contain useful tools and ingredients to aid in cooking. -- ```SOURCE_TAILORING``` For NPC AI, this location may contain useful tools for tailoring. -- ```SOURCE_DRINK``` For NPC AI, this location may contain drink for looting. -- ```SOURCE_VEHICLES``` For NPC AI, this location may contain vehicles/parts/vehicle tools, to loot. -- ```SOURCE_ELECTRONICS``` For NPC AI, this location may contain useful electronics to loot. -- ```SOURCE_CONSTRUCTION``` For NPC AI, this location may contain useful tools/components for construction. -- ```SOURCE_CHEMISTRY``` For NPC AI, this location may contain useful chemistry tools/components. -- ```SOURCE_CLOTHING``` For NPC AI, this location may contain useful clothing to loot. -- ```SOURCE_SAFETY``` For NPC AI, this location may be safe/sheltered and a good place for a base. -- ```SOURCE_ANIMALS``` For NPC AI, this location may contain useful animals for farming/riding. -- ```SOURCE_MEDICINE``` For NPC AI, this location may contain useful medicines for looting. -- ```SOURCE_LUXURY``` For NPC AI, this location may contain valuable/feel-good items to sell/keep. -- ```SOURCE_PEOPLE``` For NPC AI, this location may have other survivors. -- ```RISK_HIGH``` For NPC AI, this location has a high risk associated with it - labs/superstores etc. -- ```RISK_LOW``` For NPC AI, this location is secluded and remote, and appears to be safe. -- ```GENERIC_LOOT``` This is a place that may contain any of the above, but at a lower frequency - usually a house. +- `KNOWN_DOWN` There's a known way down. +- `KNOWN_UP` There's a known way up. +- `LINEAR` For roads etc, which use ID_straight, ID_curved, ID_tee, ID_four_way. +- `NO_ROTATE` The terrain can't be rotated (ID_north, ID_east, ID_south, and ID_west instances will + NOT be generated, just ID). +- `RIVER` It's a river tile. +- `SIDEWALK` Has sidewalks on the sides adjacent to roads. +- `LAKE` Consider this location to be a valid lake terrain for mapgen purposes. +- `LAKE_SHORE` Consider this location to be a valid lake shore terrain for mapgen purposes. +- `SOURCE_FUEL` For NPC AI, this location may contain fuel for looting. +- `SOURCE_FOOD` For NPC AI, this location may contain food for looting. +- `SOURCE_FARMING` For NPC AI, this location may contain useful farming supplies for looting. +- `SOURCE_FABRICATION` For NPC AI, this location may contain fabrication tools and components for + looting. +- `SOURCE_GUN` For NPC AI, this location may contain guns for looting. +- `SOURCE_AMMO` For NPC AI, this location may contain ammo for looting. +- `SOURCE_BOOKS` For NPC AI, this location may contain books for looting. +- `SOURCE_WEAPON` For NPC AI, this location may contain weapons for looting. +- `SOURCE_FORAGE` For NPC AI, this location may contain plants to forage. +- `SOURCE_COOKING` For NPC AI, this location may contain useful tools and ingredients to aid in + cooking. +- `SOURCE_TAILORING` For NPC AI, this location may contain useful tools for tailoring. +- `SOURCE_DRINK` For NPC AI, this location may contain drink for looting. +- `SOURCE_VEHICLES` For NPC AI, this location may contain vehicles/parts/vehicle tools, to loot. +- `SOURCE_ELECTRONICS` For NPC AI, this location may contain useful electronics to loot. +- `SOURCE_CONSTRUCTION` For NPC AI, this location may contain useful tools/components for + construction. +- `SOURCE_CHEMISTRY` For NPC AI, this location may contain useful chemistry tools/components. +- `SOURCE_CLOTHING` For NPC AI, this location may contain useful clothing to loot. +- `SOURCE_SAFETY` For NPC AI, this location may be safe/sheltered and a good place for a base. +- `SOURCE_ANIMALS` For NPC AI, this location may contain useful animals for farming/riding. +- `SOURCE_MEDICINE` For NPC AI, this location may contain useful medicines for looting. +- `SOURCE_LUXURY` For NPC AI, this location may contain valuable/feel-good items to sell/keep. +- `SOURCE_PEOPLE` For NPC AI, this location may have other survivors. +- `RISK_HIGH` For NPC AI, this location has a high risk associated with it - labs/superstores etc. +- `RISK_LOW` For NPC AI, this location is secluded and remote, and appears to be safe. +- `GENERIC_LOOT` This is a place that may contain any of the above, but at a lower frequency - + usually a house. ## Recipes ### Categories -- ```CC_AMMO``` -- ```CC_ARMOR``` -- ```CC_CHEM``` -- ```CC_DRINK``` -- ```CC_ELECTRONIC``` -- ```CC_FOOD``` -- ```CC_MISC``` -- ```CC_WEAPON``` +- `CC_AMMO` +- `CC_ARMOR` +- `CC_CHEM` +- `CC_DRINK` +- `CC_ELECTRONIC` +- `CC_FOOD` +- `CC_MISC` +- `CC_WEAPON` ### Flags -- ```ALLOW_ROTTEN``` Explicitly allow rotten components when crafting non-perishables. -- ```BLIND_EASY``` Easy to craft with little to no light. -- ```BLIND_HARD``` Possible to craft with little to no light, but difficult. -- ```SECRET``` Not automatically learned at character creation time based on high skill levels. -- ```UNCRAFT_LIQUIDS_CONTAINED``` Spawn liquid items in its default container. -- ```FULL_MAGAZINE``` If this recipe requires magazines, it needs one that is full. For deconstruction recipes, it will spawn a full magazine when deconstructed. - +- `ALLOW_ROTTEN` Explicitly allow rotten components when crafting non-perishables. +- `BLIND_EASY` Easy to craft with little to no light. +- `BLIND_HARD` Possible to craft with little to no light, but difficult. +- `SECRET` Not automatically learned at character creation time based on high skill levels. +- `UNCRAFT_LIQUIDS_CONTAINED` Spawn liquid items in its default container. +- `FULL_MAGAZINE` If this recipe requires magazines, it needs one that is full. For deconstruction + recipes, it will spawn a full magazine when deconstructed. ## Scenarios ### Flags -- ```ALLOW_OUTSIDE``` Allows placing player outside of building, useful for outdoor start. -- ```BAD_DAY``` Player starts the game drunk, depressed and sick with the flu. -- ```BOARDED``` Start in boarded building (windows and doors are boarded, movable furniture is moved to windows and doors). -- ```BORDERED``` Initial start location is bordered by an enormous wall of solid rock. -- ```CHALLENGE``` Game won't choose this scenario in random game types. -- ```CITY_START``` Scenario is available only when city size value in world options is more than 0. -- ```FIRE_START``` Player starts the game with fire nearby. -- ```HELI_CRASH``` Player starts the game with various limbs wounds. -- ```INFECTED``` Player starts the game infected. -- ```LONE_START``` If starting NPC spawn option is switched to "Scenario-based", this scenario won't spawn a fellow NPC on game start. -- ```SCEN_ONLY``` Profession can be chosen only as part of the appropriate scenario. -- ```SUR_START``` Surrounded start, zombies outside the starting location. +- `ALLOW_OUTSIDE` Allows placing player outside of building, useful for outdoor start. +- `BAD_DAY` Player starts the game drunk, depressed and sick with the flu. +- `BOARDED` Start in boarded building (windows and doors are boarded, movable furniture is moved to + windows and doors). +- `BORDERED` Initial start location is bordered by an enormous wall of solid rock. +- `CHALLENGE` Game won't choose this scenario in random game types. +- `CITY_START` Scenario is available only when city size value in world options is more than 0. +- `FIRE_START` Player starts the game with fire nearby. +- `HELI_CRASH` Player starts the game with various limbs wounds. +- `INFECTED` Player starts the game infected. +- `LONE_START` If starting NPC spawn option is switched to "Scenario-based", this scenario won't + spawn a fellow NPC on game start. +- `SCEN_ONLY` Profession can be chosen only as part of the appropriate scenario. +- `SUR_START` Surrounded start, zombies outside the starting location. #### Season Flags -- ```AUT_START``` ... start in autumn. -- ```SPR_START``` ... start in spring. -- ```SUM_ADV_START``` ... start second summer after Cataclysm. -- ```SUM_START``` ... start in summer. -- ```WIN_START``` ... start in winter. - +- `AUT_START` ... start in autumn. +- `SPR_START` ... start in spring. +- `SUM_ADV_START` ... start second summer after Cataclysm. +- `SUM_START` ... start in summer. +- `WIN_START` ... start in winter. ## Skills ### Tags -- ```combat_skill``` The skill is considered a combat skill. It's affected by "PACIFIST", "PRED1", "PRED2", "PRED3", and "PRED4" traits. -- ```contextual_skill``` The skill is abstract, it depends on context (an indirect item to which it's applied). Neither player nor NPCs can possess it. - +- `combat_skill` The skill is considered a combat skill. It's affected by "PACIFIST", "PRED1", + "PRED2", "PRED3", and "PRED4" traits. +- `contextual_skill` The skill is abstract, it depends on context (an indirect item to which it's + applied). Neither player nor NPCs can possess it. ## Techniques @@ -1264,19 +1410,30 @@ Techniques may be used by tools, armors, weapons and anything else that can be w ### WBLOCK_X -The following weapon techniques have some additional usage. These are defensive techniques that allow the item to assist in blocking attacks in melee, with some additional special uses. - -- ```WBLOCK_1``` "Medium blocking ability" -- ```WBLOCK_2``` "High blocking ability" -- ```WBLOCK_3``` "Very high blocking ability" - -An item with one of these techniques can be wielded to provide a bonus to damage reduced by blocking compared, or armor with the `BLOCK_WHILE_WORN` flag can also provide the use of this bonus while wearing the item, serving as a shield. Additionally, wielding or wearing an item with a combination of one of these techniques plus said flag will allow the item to block projectiles aimed at body parts the item otherwise does not cover (or is not covering, in the case of wielded items that meet those prerequisites). The chance that this will happen is based on the `coverage` percentage of the item used for its normal armor value, reduced by a penalty that depends on which blocking technique it possesses. The chance of it intercepting shots that strike the legs (again, unless the armor was set to cover the legs by default already, in which case it uses `coverage` as normal) is furtther penalized. The feet will always be vulnerable unless (for whatever reason a JSON author may devise, forcefield items for example) an item happens to be a shield that already covers the feet as armor. - - Technique | Chance to intercept (head, torso, opposing arm, etc) | Chance to intercept (legs) ------------|------------------------------------------------------|------------------------------- - WBLOCK_1 | 90% of default coverage value | 75% of default coverage value - WBLOCK_2 | 90% of default coverage value | 75% of default coverage value - WBLOCK_3 | 90% of default coverage value | 75% of default coverage value +The following weapon techniques have some additional usage. These are defensive techniques that +allow the item to assist in blocking attacks in melee, with some additional special uses. + +- `WBLOCK_1` "Medium blocking ability" +- `WBLOCK_2` "High blocking ability" +- `WBLOCK_3` "Very high blocking ability" + +An item with one of these techniques can be wielded to provide a bonus to damage reduced by blocking +compared, or armor with the `BLOCK_WHILE_WORN` flag can also provide the use of this bonus while +wearing the item, serving as a shield. Additionally, wielding or wearing an item with a combination +of one of these techniques plus said flag will allow the item to block projectiles aimed at body +parts the item otherwise does not cover (or is not covering, in the case of wielded items that meet +those prerequisites). The chance that this will happen is based on the `coverage` percentage of the +item used for its normal armor value, reduced by a penalty that depends on which blocking technique +it possesses. The chance of it intercepting shots that strike the legs (again, unless the armor was +set to cover the legs by default already, in which case it uses `coverage` as normal) is furtther +penalized. The feet will always be vulnerable unless (for whatever reason a JSON author may devise, +forcefield items for example) an item happens to be a shield that already covers the feet as armor. + +| Technique | Chance to intercept (head, torso, opposing arm, etc) | Chance to intercept (legs) | +| --------- | ---------------------------------------------------- | ----------------------------- | +| WBLOCK_1 | 90% of default coverage value | 75% of default coverage value | +| WBLOCK_2 | 90% of default coverage value | 75% of default coverage value | +| WBLOCK_3 | 90% of default coverage value | 75% of default coverage value | ## Tools @@ -1284,218 +1441,261 @@ An item with one of these techniques can be wielded to provide a bonus to damage Melee flags are fully compatible with tool flags, and vice versa. -- ```ACT_ON_RANGED_HIT``` The item should activate when thrown or fired, then immediately get processed if it spawns on the ground. -- ```ALLOWS_REMOTE_USE``` This item can be activated or reloaded from adjacent tile without picking it up. -- ```BELT_CLIP``` The item can be clipped or hooked on to a belt loop of the appropriate size (belt loops are limited by their max_volume and max_weight properties) -- ```BOMB``` It can be a remote controlled bomb. -- ```CABLE_SPOOL``` This item is a cable spool and must be processed as such. It has an internal "state" variable which may be in the states "attach_first" or "pay_out_cable" -- in the latter case, set its charges to `max_charges - dist(here, point(vars["source_x"], vars["source_y"]))`. If this results in 0 or a negative number, set its state back to "attach_first". -- ```CANNIBALISM``` The item is a food that contains human flesh, and applies all applicable effects when consumed. -- ```CHARGEDIM``` If illuminated, light intensity fades with charge, starting at 20% charge left. -- ```DIG_TOOL``` If wielded, digs thorough terrain like rock and walls, as player walks into them. If item also has ```POWERED``` flag, then it digs faster, but uses up the item's ammo as if activating it. -- ```FIRESTARTER``` Item will start fire with some difficulty. -- ```FIRE``` Item will start a fire immediately. -- ```FISH_GOOD``` When used for fishing, it's a good tool (requires that the matching use_action has been set). -- ```FISH_POOR``` When used for fishing, it's a poor tool (requires that the matching use_action has been set). -- ```HAS_RECIPE``` Used by the E-Ink tablet to indicates it's currently showing a recipe. -- ```IS_UPS``` Item is Unified Power Supply. Used in active item processing -- ```LIGHT_[X]``` Illuminates the area with light intensity `[X]` where `[X]` is an intensity value. (e.x. `LIGHT_4` or `LIGHT_100`). Note: this flags sets `itype::light_emission` field and then is removed (can't be found using `has_flag`); -- ```MC_MOBILE```, ```MC_RANDOM_STUFF```, ```MC_SCIENCE_STUFF```, ```MC_USED```, ```MC_HAS_DATA``` Memory card related flags, see `iuse.cpp` -- ```NO_DROP``` Item should never exist on map tile as a discrete item (must be contained by another item) -- ```NO_UNLOAD``` Cannot be unloaded. -- ```POWERED``` If turned ON, item uses its own source of power, instead of relying on power of the user -- ```RADIOCARITEM``` Item can be put into a remote controlled car. -- ```RADIOSIGNAL_1``` Activated per radios signal 1 (Red). -- ```RADIOSIGNAL_2``` Activated per radios signal 2 (Blue). -- ```RADIOSIGNAL_3``` Activated per radios signal 3 (Green). -- ```RADIO_ACTIVATION``` Item can be activated by a remote control (also requires RADIOSIGNAL_*). -- ```RADIO_INVOKE_PROC``` After being activated via radio signal the item will have its charges removed. Can be used for bypassing bomb countdown. -- ```RADIO_CONTROLLABLE``` It can be moved around via a remote control. -- ```RADIO_MODABLE``` Indicates the item can be made into a radio-activated item. -- ```RADIO_MOD``` The item has been made into a radio-activated item. -- ```RECHARGE``` Gain charges when placed in a cargo area with a recharge station. -- ```SAFECRACK``` This item can be used to unlock safes. -- ```USES_BIONIC_POWER``` The item has no charges of its own, and runs off of the player's bionic power. -- ```USE_UPS``` Item is charges from an UPS / it uses the charges of an UPS instead of its own. -- ```NAT_UPS``` Silences the (UPS) suffix from USE_UPS. -- ```WATER_EXTINGUISH``` Is extinguishable in water or under precipitation. Converts items (requires "reverts_to" or use_action "transform" to be set). -- ```WET``` Item is wet and will slowly dry off (e.g. towel). -- ```WIND_EXTINGUISH``` This item will be extinguished by the wind. -- ```WRITE_MESSAGE``` This item could be used to write messages on signs. +- `ACT_ON_RANGED_HIT` The item should activate when thrown or fired, then immediately get processed + if it spawns on the ground. +- `ALLOWS_REMOTE_USE` This item can be activated or reloaded from adjacent tile without picking it + up. +- `BELT_CLIP` The item can be clipped or hooked on to a belt loop of the appropriate size (belt + loops are limited by their max_volume and max_weight properties) +- `BOMB` It can be a remote controlled bomb. +- `CABLE_SPOOL` This item is a cable spool and must be processed as such. It has an internal "state" + variable which may be in the states "attach_first" or "pay_out_cable" -- in the latter case, set + its charges to `max_charges - dist(here, point(vars["source_x"], vars["source_y"]))`. If this + results in 0 or a negative number, set its state back to "attach_first". +- `CANNIBALISM` The item is a food that contains human flesh, and applies all applicable effects + when consumed. +- `CHARGEDIM` If illuminated, light intensity fades with charge, starting at 20% charge left. +- `DIG_TOOL` If wielded, digs thorough terrain like rock and walls, as player walks into them. If + item also has `POWERED` flag, then it digs faster, but uses up the item's ammo as if activating + it. +- `FIRESTARTER` Item will start fire with some difficulty. +- `FIRE` Item will start a fire immediately. +- `FISH_GOOD` When used for fishing, it's a good tool (requires that the matching use_action has + been set). +- `FISH_POOR` When used for fishing, it's a poor tool (requires that the matching use_action has + been set). +- `HAS_RECIPE` Used by the E-Ink tablet to indicates it's currently showing a recipe. +- `IS_UPS` Item is Unified Power Supply. Used in active item processing +- `LIGHT_[X]` Illuminates the area with light intensity `[X]` where `[X]` is an intensity value. + (e.x. `LIGHT_4` or `LIGHT_100`). Note: this flags sets `itype::light_emission` field and then is + removed (can't be found using `has_flag`); +- `MC_MOBILE`, `MC_RANDOM_STUFF`, `MC_SCIENCE_STUFF`, `MC_USED`, `MC_HAS_DATA` Memory card related + flags, see `iuse.cpp` +- `NO_DROP` Item should never exist on map tile as a discrete item (must be contained by another + item) +- `NO_UNLOAD` Cannot be unloaded. +- `POWERED` If turned ON, item uses its own source of power, instead of relying on power of the user +- `RADIOCARITEM` Item can be put into a remote controlled car. +- `RADIOSIGNAL_1` Activated per radios signal 1 (Red). +- `RADIOSIGNAL_2` Activated per radios signal 2 (Blue). +- `RADIOSIGNAL_3` Activated per radios signal 3 (Green). +- `RADIO_ACTIVATION` Item can be activated by a remote control (also requires RADIOSIGNAL_*). +- `RADIO_INVOKE_PROC` After being activated via radio signal the item will have its charges removed. + Can be used for bypassing bomb countdown. +- `RADIO_CONTROLLABLE` It can be moved around via a remote control. +- `RADIO_MODABLE` Indicates the item can be made into a radio-activated item. +- `RADIO_MOD` The item has been made into a radio-activated item. +- `RECHARGE` Gain charges when placed in a cargo area with a recharge station. +- `SAFECRACK` This item can be used to unlock safes. +- `USES_BIONIC_POWER` The item has no charges of its own, and runs off of the player's bionic power. +- `USE_UPS` Item is charges from an UPS / it uses the charges of an UPS instead of its own. +- `NAT_UPS` Silences the (UPS) suffix from USE_UPS. +- `WATER_EXTINGUISH` Is extinguishable in water or under precipitation. Converts items (requires + "reverts_to" or use_action "transform" to be set). +- `WET` Item is wet and will slowly dry off (e.g. towel). +- `WIND_EXTINGUISH` This item will be extinguished by the wind. +- `WRITE_MESSAGE` This item could be used to write messages on signs. ### Flags that apply to items These flags **do not apply to item types**. -Those flags are added by the game code to specific items (that specific welder, not *all* welders). - -- ```COLD``` Item is cold (see EATEN_COLD). -- ```DIRTY``` Item (liquid) was dropped on the ground and is now irreparably dirty. -- ```FIELD_DRESS_FAILED``` Corpse was damaged by unskillful field dressing. Affects butcher results. -- ```FIELD_DRESS``` Corpse was field dressed. Affects butcher results. -- ```FIT``` Reduces encumbrance by one. -- ```FROZEN``` Item is frozen solid (used by freezer). -- ```HIDDEN_ITEM``` This item cannot be seen in AIM. -- ```HOT``` Item is hot (see EATEN_HOT). -- ```LITCIG``` Marks a lit smoking item (cigarette, joint etc.). -- ```MUSHY``` FREEZERBURN item was frozen and is now mushy and tasteless and will go bad after freezing again. -- ```NO_PARASITES``` Invalidates parasites count set in food->type->comestible->parasites -- ```QUARTERED``` Corpse was quartered into parts. Affects butcher results, weight, volume. -- ```REVIVE_SPECIAL``` ... Corpses revives when the player is nearby. -- ```USE_UPS``` The tool has the UPS mod and is charged from an UPS. -- ```WARM``` A hidden flag used to track an item's journey to/from hot, buffers between HOT and cold. -- ```WET``` Item is wet and will slowly dry off (e.g. towel). - +Those flags are added by the game code to specific items (that specific welder, not _all_ welders). + +- `COLD` Item is cold (see EATEN_COLD). +- `DIRTY` Item (liquid) was dropped on the ground and is now irreparably dirty. +- `FIELD_DRESS_FAILED` Corpse was damaged by unskillful field dressing. Affects butcher results. +- `FIELD_DRESS` Corpse was field dressed. Affects butcher results. +- `FIT` Reduces encumbrance by one. +- `FROZEN` Item is frozen solid (used by freezer). +- `HIDDEN_ITEM` This item cannot be seen in AIM. +- `HOT` Item is hot (see EATEN_HOT). +- `LITCIG` Marks a lit smoking item (cigarette, joint etc.). +- `MUSHY` FREEZERBURN item was frozen and is now mushy and tasteless and will go bad after freezing + again. +- `NO_PARASITES` Invalidates parasites count set in food->type->comestible->parasites +- `QUARTERED` Corpse was quartered into parts. Affects butcher results, weight, volume. +- `REVIVE_SPECIAL` ... Corpses revives when the player is nearby. +- `USE_UPS` The tool has the UPS mod and is charged from an UPS. +- `WARM` A hidden flag used to track an item's journey to/from hot, buffers between HOT and cold. +- `WET` Item is wet and will slowly dry off (e.g. towel). ## Vehicle Parts ### Flags -- ```ADVANCED_PLANTER``` This planter doesn't spill seeds and avoids damaging itself on non-diggable surfaces. -- ```AISLE_LIGHT``` -- ```AISLE``` Player can move over this part with less speed penalty than normal. -- ```ALTERNATOR``` Recharges batteries installed on the vehicle. Can only be installed on a part with ```E_ALTERNATOR``` flag. -- ```ANCHOR_POINT``` Allows secure seatbelt attachment. -- ```ANIMAL_CTRL``` Can harness an animal, need HARNESS_bodytype flag to specify bodytype of animal. -- ```ARMOR``` Protects the other vehicle parts it's installed over during collisions. -- ```ATOMIC_LIGHT``` -- ```AUTOCLAVE``` Acts as an autoclave. -- ```AUTOPILOT``` This part will enable a vehicle to have a simple autopilot. -- ```BATTERY_MOUNT``` -- ```BED``` A bed where the player can sleep. -- ```BEEPER``` Generates noise when the vehicle moves backward. -- ```BELTABLE``` Seatbelt can be attached to this part. -- ```BIKE_RACK_VEH``` Can be used to merge an adjacent single tile wide vehicle, or split a single tile wide vehicle off into its own vehicle. -- ```BOARDABLE``` The player can safely move over or stand on this part while the vehicle is moving. -- ```CAMERA_CONTROL``` -- ```CAMERA``` -- ```CAPTURE_MOSNTER_VEH``` Can be used to capture monsters when mounted on a vehicle. -- ```CARGO_LOCKING``` This cargo area is inaccessible to NPCs. Can only be installed on a part with ```LOCKABLE_CARGO``` flag. -- ```CARGO``` Cargo holding area. -- ```CHEMLAB``` Acts as a chemistry set for crafting. -- ```CHIMES``` Generates continuous noise when used. -- ```CIRCLE_LIGHT``` Projects a circular radius of light when turned on. -- ```CONE_LIGHT``` Projects a cone of light when turned on. -- ```CONTROL_ANIMAL``` These controls can only be used to control a vehicle pulled by an animal (such as reins etc). -- ```CONTROLS``` Can be used to control the vehicle. -- ```COOLER``` There is separate command to toggle this part. -- ```COVERED``` Prevents items in cargo parts from emitting any light. -- ```CRAFTRIG``` Acts as a dehydrator, vacuum sealer and reloading press for crafting purposes. Potentially to include additional tools in the future. -- ```CTRL_ELECTRONIC``` Controls electrical and electronic systems of the vehicle. -- ```CURTAIN``` Can be installed over a part flagged with ```WINDOW```, and functions the same as blinds found on windows in buildings. -- ```DIFFICULTY_REMOVE``` -- ```DISHWASHER``` Can be used to wash filthy non-soft items en masse. -- ```DOME_LIGHT``` -- ```DOOR_MOTOR``` Can only be installed on a part with ```OPENABLE``` flag. -- ```E_ALTERNATOR``` Is an engine that can power an alternator. -- ```E_COLD_START``` Is an engine that starts much slower in cold weather. -- ```E_COMBUSTION``` Is an engine that burns its fuel and can backfire or explode when damaged. -- ```E_HEATER``` Is an engine and has a heater to warm internal vehicle items when on. -- ```E_HIGHER_SKILL``` Is an engine that is more difficult to install as more engines are installed. -- ```E_NO_POWER_DECAY``` Engines with this flag do not affect total vehicle power suffering diminishing returns. -- ```E_STARTS_INSTANTLY``` Is an engine that starts instantly, like food pedals. -- ```EMITTER``` Emits while enabled (emissions are defined by ```emissions``` entry). -- ```ENABLED_DRAINS_EPOWER``` Produces `epower` watts while enabled (use negative numbers to drain power). This is independent from reactor power production. -- ```ENGINE``` Is an engine and contributes towards vehicle mechanical power. -- ```EVENTURN``` Only on during even turns. -- ```EXTENDS_VISION``` Extends player vision (cameras, mirrors, etc.) -- ```EXTRA_DRAG``` tells the vehicle that the part exerts engine power reduction. -- ```FAUCET``` -- ```FLAT_SURF``` Part with a flat hard surface (e.g. table). -- ```FLOATS``` Provide buoyancy to boats -- ```FLUIDTANK``` Is a fluid tank. -- ```FOLDABLE``` -- ```FORGE``` Acts as a forge for crafting. -- ```FREEZER``` Can freeze items in below zero degrees Celsius temperature. -- ```FRIDGE``` Can refrigerate items. -- ```FUNNEL``` -- ```HALF_CIRCLE_LIGHT``` Projects a directed half-circular radius of light when turned on. -- ```HARNESS_bodytype``` Replace bodytype with `any` to accept any type, or with the targeted type. -- ```HORN``` Generates noise when used. -- ```INITIAL_PART``` When starting a new vehicle via the construction menu, this vehicle part will be the initial part of the vehicle (if the used item matches the item required for this part). The items of parts with this flag are automatically added as component to the vehicle start construction. -- ```INTERNAL``` Can only be installed on a part with ```CARGO``` flag. -- ```KITCHEN``` Acts as a kitchen unit and heat source for crafting. -- ```LIGHT``` -- ```LOCKABLE_CARGO``` Cargo containers that are able to have a lock installed. -- ```MOUNTABLE``` Player can fire mounted weapons from here. -- ```MUFFLER``` Muffles the noise a vehicle makes while running. -- ```MULTISQUARE``` Causes this part and any adjacent parts with the same ID to act as a singular part. -- ```MUSCLE_ARMS``` Power of the engine with such flag depends on player's strength (it's less effective than ```MUSCLE_LEGS```). -- ```MUSCLE_LEGS``` Power of the engine with such flag depends on player's strength. -- ```NAILABLE``` Attached with nails -- ```NEEDS_BATTERY_MOUNT``` -- ```NEEDS_WHEEL_MOUNT_HEAVY``` Can only be installed on a part with ```WHEEL_MOUNT_HEAVY``` flag. -- ```NEEDS_WHEEL_MOUNT_LIGHT``` Can only be installed on a part with ```WHEEL_MOUNT_LIGHT``` flag. -- ```NEEDS_WHEEL_MOUNT_MEDIUM``` Can only be installed on a part with ```WHEEL_MOUNT_MEDIUM``` flag. -- ```NEEDS_WINDOW``` Can only be installed on a part with ```WINDOW``` flag. -- ```NO_JACK``` -- ```NOINSTALL``` Cannot be installed. -- ```OBSTACLE``` Cannot walk through part, unless the part is also ```OPENABLE```. -- ```ODDTURN``` Only on during odd turns. -- ```ON_CONTROLS``` Can only be installed on a part with ```CONTROLS``` flag. -- ```ON_ROOF``` - Parts with this flag could only be installed on a roof (parts with ```ROOF``` flag). -- ```OPAQUE``` Cannot be seen through. -- ```OPENABLE``` Can be opened or closed. -- ```OPENCLOSE_INSIDE``` Can be opened or closed, but only from inside the vehicle. -- ```OVER``` Can be mounted over other parts. -- ```PERPETUAL``` If paired with REACTOR, part produces electrical power without consuming fuel. -- ```PLANTER``` Plants seeds into tilled dirt, spilling them when the terrain underneath is unsuitable. It is damaged by running it over non-```DIGGABLE``` surfaces. -- ```PLOW``` Tills the soil underneath the part while active. Takes damage from unsuitable terrain at a level proportional to the speed of the vehicle. -- ```POWER_TRANSFER``` Transmits power to and from an attached thingy (probably a vehicle). -- ```PROTRUSION``` Part sticks out so no other parts can be installed over it. -- ```RAIL``` This wheel allows vehicle to move on rails. -- ```REACTOR``` When enabled, part consumes fuel to generate epower. -- ```REAPER``` Cuts down mature crops, depositing them on the square. -- ```RECHARGE``` Recharge items with the same flag. ( Currently only the rechargeable battery mod. ) -- ```REMOTE_CONTROLS``` -- ```REVERSIBLE``` Removal has identical requirements to installation but is twice as quick -- ```ROOF``` Covers a section of the vehicle. Areas of the vehicle that have a roof and roofs on surrounding sections, are considered inside. Otherwise they're outside. -- ```ROTOR``` Allows vehicle to generate lift. Actual lift depends on engine power sum of all rotor's diameters. -- ```SCOOP``` Pulls items from underneath the vehicle to the cargo space of the part. Also mops up liquids. -- ```SEAT``` A seat where the player can sit or sleep. -- ```SEATBELT``` Helps prevent the player from being ejected from the vehicle during an accident. Can only be installed on a part with ```BELTABLE``` flag. -- ```SECURITY``` -- ```SHARP``` Striking a monster with this part does cutting damage instead of bashing damage, and prevents stunning the monster. -- ```SOLAR_PANEL``` Recharges vehicle batteries when exposed to sunlight. Has a 1 in 4 chance of being broken on car generation. -- ```SPACE_HEATER``` There is separate command to toggle this part. -- ```STABLE``` Similar to `WHEEL`, but if the vehicle is only a 1x1 section, this single wheel counts as enough wheels. -- ```STEERABLE``` This wheel is steerable. -- ```STEREO``` -- ```TOOL_NONE``` Can be removed/installed without any tools -- ```TOOL_SCREWDRIVER``` Attached with screws, can be removed/installed with a screwdriver -- ```TOOL_WRENCH``` Attached with bolts, can be removed/installed with a wrench -- ```TOWEL``` Can be used to dry yourself up. -- ```TRACK``` Allows the vehicle installed on, to be marked and tracked on map. -- ```TRACKED``` Contributes to steering effectiveness but doesn't count as a steering axle for install difficulty and still contributes to drag for the center of steering calculation. -- ```TRANSFORM_TERRAIN``` Transform terrain (using rules defined in ```transform_terrain```). -- ```TURRET_CONTROLS``` If part with this flag is installed over the turret, it allows to set said turret's targeting mode to full auto. Can only be installed on a part with ```TURRET``` flag. -- ```TURRET_MOUNT``` Parts with this flag are suitable for installing turrets. -- ```TURRET``` Is a weapon turret. Can only be installed on a part with ```TURRET_MOUNT``` flag. -- ```UNMOUNT_ON_DAMAGE``` Part breaks off the vehicle when destroyed by damage. Item is new and typically undamaged. -- ```UNMOUNT_ON_MOVE``` Dismount this part when the vehicle moves. Doesn't drop the part, unless you give it special handling. -- ```VARIABLE_SIZE``` Has 'bigness' for power, wheel radius, etc. -- ```VISION``` -- ```WASHING_MACHINE``` Can be used to wash filthy clothes en masse. -- ```WATER_WHEEL``` Recharges vehicle batteries when in flowing water. -- ```WELDRIG``` Acts as a welder for crafting. -- ```WHEEL``` Counts as a wheel in wheel calculations. -- ```WIDE_CONE_LIGHT``` Projects a wide cone of light when turned on. -- ```WIND_POWERED``` This engine is powered by wind ( sails etc ). -- ```WIND_TURBINE``` Recharges vehicle batteries when exposed to wind. -- ```WINDOW``` Can see through this part and can install curtains over it. -- ```WORKBENCH``` Can craft at this part, must be paired with a workbench json entry. +- `ADVANCED_PLANTER` This planter doesn't spill seeds and avoids damaging itself on non-diggable + surfaces. +- `AISLE_LIGHT` +- `AISLE` Player can move over this part with less speed penalty than normal. +- `ALTERNATOR` Recharges batteries installed on the vehicle. Can only be installed on a part with + `E_ALTERNATOR` flag. +- `ANCHOR_POINT` Allows secure seatbelt attachment. +- `ANIMAL_CTRL` Can harness an animal, need HARNESS_bodytype flag to specify bodytype of animal. +- `ARMOR` Protects the other vehicle parts it's installed over during collisions. +- `ATOMIC_LIGHT` +- `AUTOCLAVE` Acts as an autoclave. +- `AUTOPILOT` This part will enable a vehicle to have a simple autopilot. +- `BATTERY_MOUNT` +- `BED` A bed where the player can sleep. +- `BEEPER` Generates noise when the vehicle moves backward. +- `BELTABLE` Seatbelt can be attached to this part. +- `BIKE_RACK_VEH` Can be used to merge an adjacent single tile wide vehicle, or split a single tile + wide vehicle off into its own vehicle. +- `BOARDABLE` The player can safely move over or stand on this part while the vehicle is moving. +- `CAMERA_CONTROL` +- `CAMERA` +- `CAPTURE_MOSNTER_VEH` Can be used to capture monsters when mounted on a vehicle. +- `CARGO_LOCKING` This cargo area is inaccessible to NPCs. Can only be installed on a part with + `LOCKABLE_CARGO` flag. +- `CARGO` Cargo holding area. +- `CHEMLAB` Acts as a chemistry set for crafting. +- `CHIMES` Generates continuous noise when used. +- `CIRCLE_LIGHT` Projects a circular radius of light when turned on. +- `CONE_LIGHT` Projects a cone of light when turned on. +- `CONTROL_ANIMAL` These controls can only be used to control a vehicle pulled by an animal (such as + reins etc). +- `CONTROLS` Can be used to control the vehicle. +- `COOLER` There is separate command to toggle this part. +- `COVERED` Prevents items in cargo parts from emitting any light. +- `CRAFTRIG` Acts as a dehydrator, vacuum sealer and reloading press for crafting purposes. + Potentially to include additional tools in the future. +- `CTRL_ELECTRONIC` Controls electrical and electronic systems of the vehicle. +- `CURTAIN` Can be installed over a part flagged with `WINDOW`, and functions the same as blinds + found on windows in buildings. +- `DIFFICULTY_REMOVE` +- `DISHWASHER` Can be used to wash filthy non-soft items en masse. +- `DOME_LIGHT` +- `DOOR_MOTOR` Can only be installed on a part with `OPENABLE` flag. +- `E_ALTERNATOR` Is an engine that can power an alternator. +- `E_COLD_START` Is an engine that starts much slower in cold weather. +- `E_COMBUSTION` Is an engine that burns its fuel and can backfire or explode when damaged. +- `E_HEATER` Is an engine and has a heater to warm internal vehicle items when on. +- `E_HIGHER_SKILL` Is an engine that is more difficult to install as more engines are installed. +- `E_NO_POWER_DECAY` Engines with this flag do not affect total vehicle power suffering diminishing + returns. +- `E_STARTS_INSTANTLY` Is an engine that starts instantly, like food pedals. +- `EMITTER` Emits while enabled (emissions are defined by `emissions` entry). +- `ENABLED_DRAINS_EPOWER` Produces `epower` watts while enabled (use negative numbers to drain + power). This is independent from reactor power production. +- `ENGINE` Is an engine and contributes towards vehicle mechanical power. +- `EVENTURN` Only on during even turns. +- `EXTENDS_VISION` Extends player vision (cameras, mirrors, etc.) +- `EXTRA_DRAG` tells the vehicle that the part exerts engine power reduction. +- `FAUCET` +- `FLAT_SURF` Part with a flat hard surface (e.g. table). +- `FLOATS` Provide buoyancy to boats +- `FLUIDTANK` Is a fluid tank. +- `FOLDABLE` +- `FORGE` Acts as a forge for crafting. +- `FREEZER` Can freeze items in below zero degrees Celsius temperature. +- `FRIDGE` Can refrigerate items. +- `FUNNEL` +- `HALF_CIRCLE_LIGHT` Projects a directed half-circular radius of light when turned on. +- `HARNESS_bodytype` Replace bodytype with `any` to accept any type, or with the targeted type. +- `HORN` Generates noise when used. +- `INITIAL_PART` When starting a new vehicle via the construction menu, this vehicle part will be + the initial part of the vehicle (if the used item matches the item required for this part). The + items of parts with this flag are automatically added as component to the vehicle start + construction. +- `INTERNAL` Can only be installed on a part with `CARGO` flag. +- `KITCHEN` Acts as a kitchen unit and heat source for crafting. +- `LIGHT` +- `LOCKABLE_CARGO` Cargo containers that are able to have a lock installed. +- `MOUNTABLE` Player can fire mounted weapons from here. +- `MUFFLER` Muffles the noise a vehicle makes while running. +- `MULTISQUARE` Causes this part and any adjacent parts with the same ID to act as a singular part. +- `MUSCLE_ARMS` Power of the engine with such flag depends on player's strength (it's less effective + than `MUSCLE_LEGS`). +- `MUSCLE_LEGS` Power of the engine with such flag depends on player's strength. +- `NAILABLE` Attached with nails +- `NEEDS_BATTERY_MOUNT` +- `NEEDS_WHEEL_MOUNT_HEAVY` Can only be installed on a part with `WHEEL_MOUNT_HEAVY` flag. +- `NEEDS_WHEEL_MOUNT_LIGHT` Can only be installed on a part with `WHEEL_MOUNT_LIGHT` flag. +- `NEEDS_WHEEL_MOUNT_MEDIUM` Can only be installed on a part with `WHEEL_MOUNT_MEDIUM` flag. +- `NEEDS_WINDOW` Can only be installed on a part with `WINDOW` flag. +- `NO_JACK` +- `NOINSTALL` Cannot be installed. +- `OBSTACLE` Cannot walk through part, unless the part is also `OPENABLE`. +- `ODDTURN` Only on during odd turns. +- `ON_CONTROLS` Can only be installed on a part with `CONTROLS` flag. +- `ON_ROOF` - Parts with this flag could only be installed on a roof (parts with `ROOF` flag). +- `OPAQUE` Cannot be seen through. +- `OPENABLE` Can be opened or closed. +- `OPENCLOSE_INSIDE` Can be opened or closed, but only from inside the vehicle. +- `OVER` Can be mounted over other parts. +- `PERPETUAL` If paired with REACTOR, part produces electrical power without consuming fuel. +- `PLANTER` Plants seeds into tilled dirt, spilling them when the terrain underneath is unsuitable. + It is damaged by running it over non-`DIGGABLE` surfaces. +- `PLOW` Tills the soil underneath the part while active. Takes damage from unsuitable terrain at a + level proportional to the speed of the vehicle. +- `POWER_TRANSFER` Transmits power to and from an attached thingy (probably a vehicle). +- `PROTRUSION` Part sticks out so no other parts can be installed over it. +- `RAIL` This wheel allows vehicle to move on rails. +- `REACTOR` When enabled, part consumes fuel to generate epower. +- `REAPER` Cuts down mature crops, depositing them on the square. +- `RECHARGE` Recharge items with the same flag. ( Currently only the rechargeable battery mod. ) +- `REMOTE_CONTROLS` +- `REVERSIBLE` Removal has identical requirements to installation but is twice as quick +- `ROOF` Covers a section of the vehicle. Areas of the vehicle that have a roof and roofs on + surrounding sections, are considered inside. Otherwise they're outside. +- `ROTOR` Allows vehicle to generate lift. Actual lift depends on engine power sum of all rotor's + diameters. +- `SCOOP` Pulls items from underneath the vehicle to the cargo space of the part. Also mops up + liquids. +- `SEAT` A seat where the player can sit or sleep. +- `SEATBELT` Helps prevent the player from being ejected from the vehicle during an accident. Can + only be installed on a part with `BELTABLE` flag. +- `SECURITY` +- `SHARP` Striking a monster with this part does cutting damage instead of bashing damage, and + prevents stunning the monster. +- `SOLAR_PANEL` Recharges vehicle batteries when exposed to sunlight. Has a 1 in 4 chance of being + broken on car generation. +- `SPACE_HEATER` There is separate command to toggle this part. +- `STABLE` Similar to `WHEEL`, but if the vehicle is only a 1x1 section, this single wheel counts as + enough wheels. +- `STEERABLE` This wheel is steerable. +- `STEREO` +- `TOOL_NONE` Can be removed/installed without any tools +- `TOOL_SCREWDRIVER` Attached with screws, can be removed/installed with a screwdriver +- `TOOL_WRENCH` Attached with bolts, can be removed/installed with a wrench +- `TOWEL` Can be used to dry yourself up. +- `TRACK` Allows the vehicle installed on, to be marked and tracked on map. +- `TRACKED` Contributes to steering effectiveness but doesn't count as a steering axle for install + difficulty and still contributes to drag for the center of steering calculation. +- `TRANSFORM_TERRAIN` Transform terrain (using rules defined in `transform_terrain`). +- `TURRET_CONTROLS` If part with this flag is installed over the turret, it allows to set said + turret's targeting mode to full auto. Can only be installed on a part with `TURRET` flag. +- `TURRET_MOUNT` Parts with this flag are suitable for installing turrets. +- `TURRET` Is a weapon turret. Can only be installed on a part with `TURRET_MOUNT` flag. +- `UNMOUNT_ON_DAMAGE` Part breaks off the vehicle when destroyed by damage. Item is new and + typically undamaged. +- `UNMOUNT_ON_MOVE` Dismount this part when the vehicle moves. Doesn't drop the part, unless you + give it special handling. +- `VARIABLE_SIZE` Has 'bigness' for power, wheel radius, etc. +- `VISION` +- `WASHING_MACHINE` Can be used to wash filthy clothes en masse. +- `WATER_WHEEL` Recharges vehicle batteries when in flowing water. +- `WELDRIG` Acts as a welder for crafting. +- `WHEEL` Counts as a wheel in wheel calculations. +- `WIDE_CONE_LIGHT` Projects a wide cone of light when turned on. +- `WIND_POWERED` This engine is powered by wind ( sails etc ). +- `WIND_TURBINE` Recharges vehicle batteries when exposed to wind. +- `WINDOW` Can see through this part and can install curtains over it. +- `WORKBENCH` Can craft at this part, must be paired with a workbench json entry. ### Vehicle parts requiring other vehicle parts -The requirement for other vehicle parts is defined for a json flag by setting ```requires_flag``` for the flag. ```requires_flag``` is the other flag that a part with this flag requires. - +The requirement for other vehicle parts is defined for a json flag by setting `requires_flag` for +the flag. `requires_flag` is the other flag that a part with this flag requires. ### Fuel types -- ```NULL``` None -- ```battery``` Electrifying. -- ```diesel``` Refined dino. -- ```gasoline``` Refined dino. -- ```plasma``` Superheated. -- ```plutonium``` 1.21 Gigawatts! -- ```water``` Clean. -- ```wind``` Wind powered. +- `NULL` None +- `battery` Electrifying. +- `diesel` Refined dino. +- `gasoline` Refined dino. +- `plasma` Superheated. +- `plutonium` 1.21 Gigawatts! +- `water` Clean. +- `wind` Wind powered. diff --git a/doc/JSON_INFO.md b/doc/JSON_INFO.md index c4d7a3756b86..548f4a27f94c 100644 --- a/doc/JSON_INFO.md +++ b/doc/JSON_INFO.md @@ -5,33 +5,33 @@ Use the `Home` key to return to the top. - [Introduction](#introduction) - [Navigating the JSON](#navigating-the-json) - [File descriptions](#file-descriptions) - * [`data/json/`](#datajson) - * [`data/json/items/`](#datajsonitems) - + [`data/json/items/comestibles`](#datajsonitemscomestibles) - * [`data/json/requirements/`](#datajsonrequirements) - * [`data/json/vehicles/`](#datajsonvehicles) + - [`data/json/`](#datajson) + - [`data/json/items/`](#datajsonitems) + - [`data/json/items/comestibles`](#datajsonitemscomestibles) + - [`data/json/requirements/`](#datajsonrequirements) + - [`data/json/vehicles/`](#datajsonvehicles) - [Generic properties and formatting](#generic-properties-and-formatting) - * [Generic properties](#generic-properties) - * [Formatting](#formatting) - + [Time duration](#time-duration) - + [Other formatting](#other-formatting) + - [Generic properties](#generic-properties) + - [Formatting](#formatting) + - [Time duration](#time-duration) + - [Other formatting](#other-formatting) - [Description and content of each JSON file](#description-and-content-of-each-json-file) - * [`data/json/` JSONs](#datajson-jsons) - + [Ascii_arts](#ascii_arts) - + [Body_parts](#body_parts) - + [Bionics](#bionics) - + [Dreams](#dreams) - + [Disease](#disease_type) - + [Item Groups](#item-groups) - + [Item Category](#item-category) - + [Materials](#materials) - + [Monster Groups](#monster-groups) + - [`data/json/` JSONs](#datajson-jsons) + - [Ascii_arts](#ascii_arts) + - [Body_parts](#body_parts) + - [Bionics](#bionics) + - [Dreams](#dreams) + - [Disease](#disease_type) + - [Item Groups](#item-groups) + - [Item Category](#item-category) + - [Materials](#materials) + - [Monster Groups](#monster-groups) - [Group definition](#group-definition) - [Monster definition](#monster-definition) - + [Monster Factions](#monster-factions) - + [Monsters](#monsters) - + [Names](#names) - + [Profession item substitution](#profession-item-substitution) + - [Monster Factions](#monster-factions) + - [Monsters](#monsters) + - [Names](#names) + - [Profession item substitution](#profession-item-substitution) - [`description`](#-description-) - [`name`](#-name-) - [`points`](#-points-) @@ -42,223 +42,236 @@ Use the `Home` key to return to the top. - [`flags`](#-flags-) - [`cbms`](#-cbms-) - [`traits`](#-traits-) - + [Recipes](#recipes) - + [Constructions](#constructions) - + [Construction groups](#construction-groups) - + [Construction sequences](#construction-sequences) - + [Scent Types](#scent_types) - + [Scores and Achievements](#scores-and-achievements) + - [Recipes](#recipes) + - [Constructions](#constructions) + - [Construction groups](#construction-groups) + - [Construction sequences](#construction-sequences) + - [Scent Types](#scent_types) + - [Scores and Achievements](#scores-and-achievements) - [`event_transformation`](#event_transformation) - [`event_statistic`](#event_statistic) - [`score`](#score) - [`achievement`](#achievement) - + [Skills](#skills) - + [Traits/Mutations](#traits-mutations) - + [Vehicle Groups](#vehicle-groups) - + [Vehicle Parts](#vehicle-parts) - + [Part Resistance](#part-resistance) - + [Vehicle Placement](#vehicle-placement) - + [Vehicle Spawn](#vehicle-spawn) - + [Vehicles](#vehicles) + - [Skills](#skills) + - [Traits/Mutations](#traits-mutations) + - [Vehicle Groups](#vehicle-groups) + - [Vehicle Parts](#vehicle-parts) + - [Part Resistance](#part-resistance) + - [Vehicle Placement](#vehicle-placement) + - [Vehicle Spawn](#vehicle-spawn) + - [Vehicles](#vehicles) - [`data/json/items/` JSONs](#datajsonitems-jsons) - + [Generic Items](#generic-items) - + [Ammo](#ammo) - + [Magazine](#magazine) - + [Armor](#armor) - + [Pet Armor](#pet-armor) - + [Books](#books) - - [Color Key](#color-key) - + [Comestibles](#comestibles) - + [Containers](#containers) - + [Melee](#melee) - - [`Melee Weapon_category`](#melee-weapon_category) - + [Gun](#gun) - - [`Ranged Weapon_category`](#ranged-weapon_category) - + [Gunmod](#gunmod) - + [Batteries](#batteries) - + [Tools](#tools) - + [Seed Data](#seed-data) - + [Brewing Data](#brewing-data) - + [Relic Data](#relic-data) - + [Artifact Data](#artifact-data) - - [`Effects_carried`](#effects-carried) - - [`effects_worn`](#effects-worn) - - [`effects_wielded`](#effects-wielded) - - [`effects_activated`](#effects-activated) - + [Software Data](#software-data) - + [Fuel data](#fuel-data) - + [Use Actions](#use-actions) + - [Generic Items](#generic-items) + - [Ammo](#ammo) + - [Magazine](#magazine) + - [Armor](#armor) + - [Pet Armor](#pet-armor) + - [Books](#books) + - [Color Key](#color-key) + - [Comestibles](#comestibles) + - [Containers](#containers) + - [Melee](#melee) + - [`Melee Weapon_category`](#melee-weapon_category) + - [Gun](#gun) + - [`Ranged Weapon_category`](#ranged-weapon_category) + - [Gunmod](#gunmod) + - [Batteries](#batteries) + - [Tools](#tools) + - [Seed Data](#seed-data) + - [Brewing Data](#brewing-data) + - [Relic Data](#relic-data) + - [Artifact Data](#artifact-data) + - [`Effects_carried`](#effects-carried) + - [`effects_worn`](#effects-worn) + - [`effects_wielded`](#effects-wielded) + - [`effects_activated`](#effects-activated) + - [Software Data](#software-data) + - [Fuel data](#fuel-data) + - [Use Actions](#use-actions) - [`json/` JSONs](#json-jsons) - + [Harvest](#harvest) - - [`id`](#-id-) - - [`type`](#-type-) - - [`message`](#-message-) - - [`entries`](#-entries-) - + [Furniture](#furniture) - - [`type`](#-type--1) - - [`move_cost_mod`](#-move-cost-mod-) - - [`light_emitted`](#-light-emitted-) - - [`required_str`](#-required-str-) - - [`crafting_pseudo_item`](#-crafting-pseudo-item-) - - [`workbench`](#-workbench-) - - [`plant_data`](#-plant-data-) - + [Terrain](#terrain) - - [`type`](#-type--2) - - [`move_cost`](#-move-cost-) - - [`light_emitted`](#-light-emitted--1) - - [`trap`](#-trap-) - - [`harvestable`](#-harvestable-) - - [`transforms_into`](#-transforms-into-) - - [`harvest_season`](#-harvest-season-) - - [`roof`](#-roof-) - + [Common To Furniture And Terrain](#common-to-furniture-and-terrain) - - [`id`](#-id--1) - - [`name`](#-name--1) - - [`flags`](#-flags--1) - - [`connects_to`](#-connects-to-) - - [`symbol`](#-symbol-) - - [`looks_like`](#-looks-like-) - - [`color` or `bgcolor`](#-color--or--bgcolor-) - - [`max_volume`](#-max-volume-) - - [`examine_action`](#-examine-action-) - - [`close" And "open`](#-close--and--open-) - - [`bash`](#-bash-) - - [`deconstruct`](#-deconstruct-) - - [`pry`](#-pry-) - - [`map_bash_info`](#-map-bash-info-) - - [`str_min`, `str_max`, `str_min_blocked`, `str_max_blocked`, `str_min_supported`, `str_max_supported`](#-str-min----str-max----str-min-blocked----str-max-blocked----str-min-supported----str-max-supported-) - - [`sound`, `sound_fail`, `sound_vol`, `sound_fail_vol`](#-sound----sound-fail----sound-vol----sound-fail-vol-) - - [`furn_set`, `ter_set`](#-furn-set----ter-set-) - - [`explosive`](#-explosive-) - - [`destroy_only`](#-destroy-only-) - - [`bash_below`](#-bash-below-) - - [`tent_centers`, `collapse_radius`](#-tent-centers----collapse-radius-) - - [`items`](#-items--1) - - [`map_deconstruct_info`](#-map-deconstruct-info-) - - [`furn_set`, `ter_set`](#-furn-set----ter-set--1) - - [`items`](#-items-2) - - [`prying_result`](#-prying-result-) - - [`new_ter_type`, `new_furn_type`](#-new-furn-type----new-ter-type-) - - [`success_message`, `fail_message`, `break_message`](#-success-message----fail-message----break-message-) - - [`pry_quality`, `pry_bonus_mult`, `difficulty`](#-pry-quality----pry-bonus-mult----difficulty-) - - [`noise`, `break_noise`, `sound`, `break_sound`](#-noise----break-noise----sound----break-sound-) - - [`breakable`, `break_ter_type`, `break_furn_type`](#-breakable----break-ter-type----break-furn-type-) - - [`break_items`](#-break-items-) - + [`plant_data`](#plant_data-1) - - [`transform`](#-transform-) - - [`base`](#-base-) - - [`growth_multiplier`](#-growth-multiplier-) - - [`harvest_multiplier`](#-harvest-multiplier-) - + [clothing_mod](#clothing_mod) + - [Harvest](#harvest) + - [`id`](#-id-) + - [`type`](#-type-) + - [`message`](#-message-) + - [`entries`](#-entries-) + - [Furniture](#furniture) + - [`type`](#-type--1) + - [`move_cost_mod`](#-move-cost-mod-) + - [`light_emitted`](#-light-emitted-) + - [`required_str`](#-required-str-) + - [`crafting_pseudo_item`](#-crafting-pseudo-item-) + - [`workbench`](#-workbench-) + - [`plant_data`](#-plant-data-) + - [Terrain](#terrain) + - [`type`](#-type--2) + - [`move_cost`](#-move-cost-) + - [`light_emitted`](#-light-emitted--1) + - [`trap`](#-trap-) + - [`harvestable`](#-harvestable-) + - [`transforms_into`](#-transforms-into-) + - [`harvest_season`](#-harvest-season-) + - [`roof`](#-roof-) + - [Common To Furniture And Terrain](#common-to-furniture-and-terrain) + - [`id`](#-id--1) + - [`name`](#-name--1) + - [`flags`](#-flags--1) + - [`connects_to`](#-connects-to-) + - [`symbol`](#-symbol-) + - [`looks_like`](#-looks-like-) + - [`color` or `bgcolor`](#-color--or--bgcolor-) + - [`max_volume`](#-max-volume-) + - [`examine_action`](#-examine-action-) + - [`close" And "open`](#-close--and--open-) + - [`bash`](#-bash-) + - [`deconstruct`](#-deconstruct-) + - [`pry`](#-pry-) + - [`map_bash_info`](#-map-bash-info-) + - [`str_min`, `str_max`, `str_min_blocked`, `str_max_blocked`, `str_min_supported`, `str_max_supported`](#-str-min----str-max----str-min-blocked----str-max-blocked----str-min-supported----str-max-supported-) + - [`sound`, `sound_fail`, `sound_vol`, `sound_fail_vol`](#-sound----sound-fail----sound-vol----sound-fail-vol-) + - [`furn_set`, `ter_set`](#-furn-set----ter-set-) + - [`explosive`](#-explosive-) + - [`destroy_only`](#-destroy-only-) + - [`bash_below`](#-bash-below-) + - [`tent_centers`, `collapse_radius`](#-tent-centers----collapse-radius-) + - [`items`](#-items--1) + - [`map_deconstruct_info`](#-map-deconstruct-info-) + - [`furn_set`, `ter_set`](#-furn-set----ter-set--1) + - [`items`](#-items-2) + - [`prying_result`](#-prying-result-) + - [`new_ter_type`, `new_furn_type`](#-new-furn-type----new-ter-type-) + - [`success_message`, `fail_message`, `break_message`](#-success-message----fail-message----break-message-) + - [`pry_quality`, `pry_bonus_mult`, `difficulty`](#-pry-quality----pry-bonus-mult----difficulty-) + - [`noise`, `break_noise`, `sound`, `break_sound`](#-noise----break-noise----sound----break-sound-) + - [`breakable`, `break_ter_type`, `break_furn_type`](#-breakable----break-ter-type----break-furn-type-) + - [`break_items`](#-break-items-) + - [`plant_data`](#plant_data-1) + - [`transform`](#-transform-) + - [`base`](#-base-) + - [`growth_multiplier`](#-growth-multiplier-) + - [`harvest_multiplier`](#-harvest-multiplier-) + - [clothing_mod](#clothing_mod) - [Scenarios](#scenarios) - * [`description`](#-description--1) - * [`name`](#-name--2) - * [`points`](#-points--1) - * [`items`](#-items--3) - * [`flags`](#-flags--2) - * [`cbms`](#-cbms--1) - * [`traits", "forced_traits", "forbidden_traits`](#-traits----forced-traits----forbidden-traits-) - * [`allowed_locs`](#-allowed-locs-) - * [`start_name`](#-start-name-) - * [`professions`](#-professions-) - * [`map_special`](#-map-special-) - * [`missions`](#-missions-) + - [`description`](#-description--1) + - [`name`](#-name--2) + - [`points`](#-points--1) + - [`items`](#-items--3) + - [`flags`](#-flags--2) + - [`cbms`](#-cbms--1) + - [`traits", "forced_traits", "forbidden_traits`](#-traits----forced-traits----forbidden-traits-) + - [`allowed_locs`](#-allowed-locs-) + - [`start_name`](#-start-name-) + - [`professions`](#-professions-) + - [`map_special`](#-map-special-) + - [`missions`](#-missions-) - [Starting locations](#starting-locations) - * [`name`](#-name--3) - * [`target`](#-target-) - * [`flags`](#-flags--3) - + [`tile_config`](#-tile-config-) + - [`name`](#-name--3) + - [`target`](#-target-) + - [`flags`](#-flags--3) + - [`tile_config`](#-tile-config-) - [Mutation overlay ordering](#mutation-overlay-ordering) - * [`id`](#-id--2) - * [`order`](#-order-) + - [`id`](#-id--2) + - [`order`](#-order-) - [MOD_INFO](#mod_info) - [MOD tileset](#mod-tileset) - * [`compatibility`](#-compatibility-) - * [`tiles-new`](#-tiles-new-) + - [`compatibility`](#-compatibility-) + - [`tiles-new`](#-tiles-new-) - [Field types](#-field-types-) # Introduction -This document describes the contents of the json files used in Cataclysm: Dark days ahead. You are probably reading this if you want to add or change content of Catacysm: Dark days ahead and need to learn more about what to find where and what each file and property does. + +This document describes the contents of the json files used in Cataclysm: Dark days ahead. You are +probably reading this if you want to add or change content of Catacysm: Dark days ahead and need to +learn more about what to find where and what each file and property does. # Navigating the JSON -A lot of the JSON involves cross-references to other JSON entities. To make it easier to navigate, we provide a script `tools/json_tools/cddatags.py` that can build a `tags` file for you. -To run the script you'll need Python 3. On Windows you'll probably need to install that, and associate `.py` files with Python. Then open a command prompt, navigate to your CDDA folder, and run `tools\json_tools\cddatags.py`. +A lot of the JSON involves cross-references to other JSON entities. To make it easier to navigate, +we provide a script `tools/json_tools/cddatags.py` that can build a `tags` file for you. + +To run the script you'll need Python 3. On Windows you'll probably need to install that, and +associate `.py` files with Python. Then open a command prompt, navigate to your CDDA folder, and run +`tools\json_tools\cddatags.py`. -To use this feature your editor will need [ctags support](http://ctags.sourceforge.net/). When that's working you should be able to easily jump to the definition of any entity. For example, by positioning your cursor over an id and hitting the appropriate key combination. +To use this feature your editor will need [ctags support](http://ctags.sourceforge.net/). When +that's working you should be able to easily jump to the definition of any entity. For example, by +positioning your cursor over an id and hitting the appropriate key combination. -* In Vim, this feature exists by default, and you can jump to a definition using [`^]`](http://vimdoc.sourceforge.net/htmldoc/tagsrch.html#tagsrch.txt). -* In Notepad++ go to "Plugins" -> "Plugins Admin" and enable the "TagLEET" plugin. Then select any id and press Alt+Space to open the references window. +- In Vim, this feature exists by default, and you can jump to a definition using + [`^]`](http://vimdoc.sourceforge.net/htmldoc/tagsrch.html#tagsrch.txt). +- In Notepad++ go to "Plugins" -> "Plugins Admin" and enable the "TagLEET" plugin. Then select any + id and press Alt+Space to open the references window. # File descriptions -Here's a quick summary of what each of the JSON files contain, broken down by folder. This list is not comprehensive, but covers the broad strokes. + +Here's a quick summary of what each of the JSON files contain, broken down by folder. This list is +not comprehensive, but covers the broad strokes. ## `data/json/` -| Filename | Description -|--- |--- -| achievements.json | achievements -| anatomy.json | a listing of player body parts - do not edit -| ascii_arts.json | ascii arts for item descriptions -| bionics.json | bionics, does NOT include bionic effects -| body_parts.json | an expansion of anatomy.json - do not edit -| clothing_mods.json | definition of clothing mods -| construction.json | definition of construction menu tasks -| default_blacklist.json | a standard blacklist of joke monsters -| doll_speech.json | talk doll speech messages -| dreams.json | dream text and linked mutation categories -| disease.json | disease definitions -| effects.json | common effects and their effects -| emit.json | smoke and gas emissions -| flags.json | common flags and their descriptions -| furniture.json | furniture, and features treated like furniture -| game_balance.json | various options to tweak game balance -| gates.json | gate terrain definitions -| harvest.json | item drops for butchering corpses -| health_msgs.json | messages displayed when the player wakes -| item_actions.json | descriptions of standard item actions -| item_category.json | item categories and their default sort -| item_groups.json | item spawn groups -| lab_notes.json | lab computer messages -| martialarts.json | martial arts styles and buffs -| materials.json | material types -| monster_attacks.json | monster attacks -| monster_drops.json | monster item drops on death -| monster_factions.json | monster factions -| monstergroups.json | monster spawn groups -| monstergroups_egg.json | monster spawn groups from eggs -| monsters.json | monster descriptions, mostly zombies -| morale_types.json | morale modifier messages -| mutation_category.json | messages for mutation categories -| mutation_ordering.json | draw order for mutation and CBM overlays in tiles mode -| mutations.json | traits/mutations -| names.json | names used for NPC/player name generation -| overmap_connections.json | connections for roads and tunnels in the overmap -| overmap_terrain.json | overmap terrain -| player_activities.json | player activities -| professions.json | profession definitions -| recipes.json | crafting/disassembly recipes -| regional_map_settings.json | settings for the entire map generation -| road_vehicles.json | vehicle spawn information for roads -| rotatable_symbols.json | rotatable symbols - do not edit -| scent_types.json | type of scent available -| scores.json | scores -| skills.json | skill descriptions and ID's -| snippets.json | flier/poster descriptions -| species.json | monster species -| speech.json | monster vocalizations -| statistics.json | statistics and transformations used to define scores and achievements -| start_locations.json | starting locations for scenarios -| techniques.json | generic for items and martial arts -| terrain.json | terrain types and definitions -| test_regions.json | test regions -| tips.json | tips of the day -| tool_qualities.json | standard tool qualities and their actions -| traps.json | standard traps -| tutorial.json | messages for the tutorial (that is out of date) -| vehicle_groups.json | vehicle spawn groups -| vehicle_parts.json | vehicle parts, does NOT affect flag effects -| vitamin.json | vitamins and their deficiencies +| Filename | Description | +| -------------------------- | --------------------------------------------------------------------- | +| achievements.json | achievements | +| anatomy.json | a listing of player body parts - do not edit | +| ascii_arts.json | ascii arts for item descriptions | +| bionics.json | bionics, does NOT include bionic effects | +| body_parts.json | an expansion of anatomy.json - do not edit | +| clothing_mods.json | definition of clothing mods | +| construction.json | definition of construction menu tasks | +| default_blacklist.json | a standard blacklist of joke monsters | +| doll_speech.json | talk doll speech messages | +| dreams.json | dream text and linked mutation categories | +| disease.json | disease definitions | +| effects.json | common effects and their effects | +| emit.json | smoke and gas emissions | +| flags.json | common flags and their descriptions | +| furniture.json | furniture, and features treated like furniture | +| game_balance.json | various options to tweak game balance | +| gates.json | gate terrain definitions | +| harvest.json | item drops for butchering corpses | +| health_msgs.json | messages displayed when the player wakes | +| item_actions.json | descriptions of standard item actions | +| item_category.json | item categories and their default sort | +| item_groups.json | item spawn groups | +| lab_notes.json | lab computer messages | +| martialarts.json | martial arts styles and buffs | +| materials.json | material types | +| monster_attacks.json | monster attacks | +| monster_drops.json | monster item drops on death | +| monster_factions.json | monster factions | +| monstergroups.json | monster spawn groups | +| monstergroups_egg.json | monster spawn groups from eggs | +| monsters.json | monster descriptions, mostly zombies | +| morale_types.json | morale modifier messages | +| mutation_category.json | messages for mutation categories | +| mutation_ordering.json | draw order for mutation and CBM overlays in tiles mode | +| mutations.json | traits/mutations | +| names.json | names used for NPC/player name generation | +| overmap_connections.json | connections for roads and tunnels in the overmap | +| overmap_terrain.json | overmap terrain | +| player_activities.json | player activities | +| professions.json | profession definitions | +| recipes.json | crafting/disassembly recipes | +| regional_map_settings.json | settings for the entire map generation | +| road_vehicles.json | vehicle spawn information for roads | +| rotatable_symbols.json | rotatable symbols - do not edit | +| scent_types.json | type of scent available | +| scores.json | scores | +| skills.json | skill descriptions and ID's | +| snippets.json | flier/poster descriptions | +| species.json | monster species | +| speech.json | monster vocalizations | +| statistics.json | statistics and transformations used to define scores and achievements | +| start_locations.json | starting locations for scenarios | +| techniques.json | generic for items and martial arts | +| terrain.json | terrain types and definitions | +| test_regions.json | test regions | +| tips.json | tips of the day | +| tool_qualities.json | standard tool qualities and their actions | +| traps.json | standard traps | +| tutorial.json | messages for the tutorial (that is out of date) | +| vehicle_groups.json | vehicle spawn groups | +| vehicle_parts.json | vehicle parts, does NOT affect flag effects | +| vitamin.json | vitamins and their deficiencies | selected subfolders @@ -266,33 +279,33 @@ selected subfolders See below for specifics on the various items -| Filename | Description -|--- |--- -| ammo.json | common base components like batteries and marbles -| ammo_types.json | standard ammo types by gun -| archery.json | bows and arrows -| armor.json | armor and clothing -| bionics.json | Compact Bionic Modules (CBMs) -| biosignatures.json | animal waste -| books.json | books -| chemicals_and_resources.json | chemical precursors -| comestibles.json | food/drinks -| containers.json | containers -| crossbows.json | crossbows and bolts -| fake.json | fake items for bionics or mutations -| fuel.json | liquid fuels -| grenades.json | grenades and throwable explosives -| handloaded_bullets.json | random ammo -| melee.json | anything that doesn't go in the other item jsons, melee weapons -| migration.json | conversions of non-existent items from save games to current items -| newspaper.json | flyers, newspapers, and survivor notes. snippets.json for messages -| obsolete.json | items being removed from the game -| ranged.json | guns -| software.json | software for SD-cards and USB sticks -| tool_armor.json | clothes and armor that can be (a)ctivated -| toolmod.json | modifications of tools -| tools.json | tools and items that can be (a)ctivated -| vehicle_parts.json | components of vehicles when they aren't on the vehicle +| Filename | Description | +| ---------------------------- | ------------------------------------------------------------------ | +| ammo.json | common base components like batteries and marbles | +| ammo_types.json | standard ammo types by gun | +| archery.json | bows and arrows | +| armor.json | armor and clothing | +| bionics.json | Compact Bionic Modules (CBMs) | +| biosignatures.json | animal waste | +| books.json | books | +| chemicals_and_resources.json | chemical precursors | +| comestibles.json | food/drinks | +| containers.json | containers | +| crossbows.json | crossbows and bolts | +| fake.json | fake items for bionics or mutations | +| fuel.json | liquid fuels | +| grenades.json | grenades and throwable explosives | +| handloaded_bullets.json | random ammo | +| melee.json | anything that doesn't go in the other item jsons, melee weapons | +| migration.json | conversions of non-existent items from save games to current items | +| newspaper.json | flyers, newspapers, and survivor notes. snippets.json for messages | +| obsolete.json | items being removed from the game | +| ranged.json | guns | +| software.json | software for SD-cards and USB sticks | +| tool_armor.json | clothes and armor that can be (a)ctivated | +| toolmod.json | modifications of tools | +| tools.json | tools and items that can be (a)ctivated | +| vehicle_parts.json | components of vehicles when they aren't on the vehicle | ### `data/json/items/comestibles` @@ -300,67 +313,70 @@ See below for specifics on the various items Standard components and tools for crafting -| Filename | Description -|--- |--- -| ammo.json | ammo components -| cooking_components.json | common ingredient sets -| cooking_requirements.json | cooking tools and heat sources -| materials.json | thread, fabric, and other basic materials -| toolsets.json | sets of tools commonly used together -| uncraft.json | common results of taking stuff apart -| vehicle.json | tools to work on vehicles - +| Filename | Description | +| ------------------------- | ----------------------------------------- | +| ammo.json | ammo components | +| cooking_components.json | common ingredient sets | +| cooking_requirements.json | cooking tools and heat sources | +| materials.json | thread, fabric, and other basic materials | +| toolsets.json | sets of tools commonly used together | +| uncraft.json | common results of taking stuff apart | +| vehicle.json | tools to work on vehicles | ## `data/json/vehicles/` Groups of vehicle definitions with self-explanatory names of files: -| Filename -|--- -| bikes.json -| boats.json -| cars.json -| carts.json -| custom_vehicles.json -| emergency.json -| farm.json -| helicopters.json -| military.json -| trains.json -| trucks.json -| utility.json -| vans_busses.json -| vehicles.json +| Filename | +| -------------------- | +| bikes.json | +| boats.json | +| cars.json | +| carts.json | +| custom_vehicles.json | +| emergency.json | +| farm.json | +| helicopters.json | +| military.json | +| trains.json | +| trucks.json | +| utility.json | +| vans_busses.json | +| vehicles.json | # Generic properties and formatting + This section describes properties and formatting applied to all of the JSON files. ## Generic properties -A few properties are applicable to most if not all json files and do not need to be described for each json file. These properties are: - -| Identifier | Description -|--- |--- -| type | The type of object this json entry is describing. Setting this entry to 'armor' for example means the game will expect properties specific to armor in that entry. Also ties in with 'copy-from' (see below), if you want to inherit properties of another object, it must be of the same tipe. -| [copy-from](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | The identifier of the item you wish to copy properties from. This allows you to make an exact copy of an item __of the same type__ and only provide entries that should change from the item you copied from. -| [extends](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | Modders can add an "extends" field to their definition to append entries to a list instead of overriding the entire list. -| [delete](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | Modders can also add a "delete" field that removes elements from lists instead of overriding the entire list. -| [abstract](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | Creates an abstract item (an item that does not end up in the game and solely exists in the json to be copied-from. Use this _instead of_ 'id'. +A few properties are applicable to most if not all json files and do not need to be described for +each json file. These properties are: +| Identifier | Description | +| --------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| type | The type of object this json entry is describing. Setting this entry to 'armor' for example means the game will expect properties specific to armor in that entry. Also ties in with 'copy-from' (see below), if you want to inherit properties of another object, it must be of the same tipe. | +| [copy-from](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | The identifier of the item you wish to copy properties from. This allows you to make an exact copy of an item **of the same type** and only provide entries that should change from the item you copied from. | +| [extends](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | Modders can add an "extends" field to their definition to append entries to a list instead of overriding the entire list. | +| [delete](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | Modders can also add a "delete" field that removes elements from lists instead of overriding the entire list. | +| [abstract](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/doc/JSON_INHERITANCE.md) | Creates an abstract item (an item that does not end up in the game and solely exists in the json to be copied-from. Use this _instead of_ 'id'. | ## Formatting + When editing JSON files make sure you apply the correct formatting as shown below. ### Time duration -A string containing one or more pairs of number and time duration unit. Number and unit, as well as each pair, can be separated by an arbitrary amount of spaces. -Available units: +A string containing one or more pairs of number and time duration unit. Number and unit, as well as +each pair, can be separated by an arbitrary amount of spaces. Available units: + - "hours", "hour", "h" - one hour - "days", "day", "d" - one day - "minutes", "minute", "m" - one minute - "turns", "turn", "t" - one turn, Examples: + - " +1 day -23 hours 50m " `(1*24*60 - 23*60 + 50 == 110 minutes)` - "1 turn 1 minutes 9 turns" (1 minute and 10 seconds because 1 turn is 1 second) @@ -370,7 +386,10 @@ Examples: "//" : "comment", // Preferred method of leaving comments inside json files. ``` -Some json strings are extracted for translation, for example item names, descriptions, etc. The exact extraction is handled in `lang/extract_json_strings.py`. Apart from the obvious way of writing a string without translation context, the string can also have an optional translation context (and sometimes a plural form), by writing it like: +Some json strings are extracted for translation, for example item names, descriptions, etc. The +exact extraction is handled in `lang/extract_json_strings.py`. Apart from the obvious way of writing +a string without translation context, the string can also have an optional translation context (and +sometimes a plural form), by writing it like: ```JSON "name": { "ctxt": "foo", "str": "bar", "str_pl": "baz" } @@ -382,8 +401,8 @@ or, if the plural form is the same as the singular form: "name": { "ctxt": "foo", "str_sp": "foo" } ``` -You can also add comments for translators by adding a "//~" entry like below. The -order of the entries does not matter. +You can also add comments for translators by adding a "//~" entry like below. The order of the +entries does not matter. ```JSON "name": { @@ -392,134 +411,139 @@ order of the entries does not matter. } ``` -Currently, only some JSON values support this syntax (see [here](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/TRANSLATING.md#translation) for a list of supported values and more detailed explanation). +Currently, only some JSON values support this syntax (see +[here](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/TRANSLATING.md#translation) for +a list of supported values and more detailed explanation). # Description and content of each JSON file -This section describes each json file and their contents. Each json has their own unique properties that are not shared with other Json files (for example 'chapters' property used in books does not apply to armor). This will make sure properties are only described and used within the context of the appropriate JSON file. +This section describes each json file and their contents. Each json has their own unique properties +that are not shared with other Json files (for example 'chapters' property used in books does not +apply to armor). This will make sure properties are only described and used within the context of +the appropriate JSON file. ## `data/json/` JSONs ### Ascii_arts -| Identifier | Description -|--- |--- -| id | Unique ID. Must be one continuous word, use underscores if necessary. -| picture | Array of string, each entry is a line of an ascii picture and must be at most 42 columns long. +| Identifier | Description | +| ---------- | ---------------------------------------------------------------------------------------------- | +| id | Unique ID. Must be one continuous word, use underscores if necessary. | +| picture | Array of string, each entry is a line of an ascii picture and must be at most 42 columns long. | ```C++ - { - "type": "ascii_art", - "id": "cashcard", - "picture": [ - "", - "", - "", - " ╔═══════════════════╗", - " ║ ║", - " ╔═ ╔═╔═╗╔═║ ║ ║", - " ║═ ┼ ║ ║═║╚╗║═║ ║", - " ╚═ ╚═║ ║═╝║ ║ ║", - " ║ ║", - " ║ RIVTECH TRUST ║", - " ║ ║", - " ║ ║", - " ║ 555 993 55221 066 ║", - " ╚═══════════════════╝" - ] - } +{ + "type": "ascii_art", + "id": "cashcard", + "picture": [ + "", + "", + "", + " ╔═══════════════════╗", + " ║ ║", + " ╔═ ╔═╔═╗╔═║ ║ ║", + " ║═ ┼ ║ ║═║╚╗║═║ ║", + " ╚═ ╚═║ ║═╝║ ║ ║", + " ║ ║", + " ║ RIVTECH TRUST ║", + " ║ ║", + " ║ ║", + " ║ 555 993 55221 066 ║", + " ╚═══════════════════╝" + ] +} ``` ### Body_parts -| Identifier | Description -|--- |--- -| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. -| name | (_mandatory_) In-game name displayed. -| accusative | (_mandatory_) Accusative form for this bodypart. -| heading | (_mandatory_) How it's displayed in headings. -| heading_multiple | (_optional_) Plural form of heading. (default: heading value) -| hp_bar_ui_text | (_optional_) How it's displayed next to the hp bar in the panel. (default: empty string) -| encumbrance_text | (_optional_) Description of effect when encumbered. (default: empty string) -| main_part | (_optional_) What is the main part this one is attached to. (default: self) -| base_hp | (_optional_) The amount of hp this part has before any modification. (default: `60`) -| opposite_part | (_optional_) What is the opposite part ot this one in case of a pair. (default: self) -| essential | (_optional_) Whether the character dies if this part drops to `0` HP. -| hit_size | (_optional_) Float. Size of the body part when doing an unweighted selection. (default: `0.`) -| hit_size_relative | (_optional_) Float. Hit sizes for attackers who are smaller, equal in size, and bigger. (default: `[ 0, 0, 0 ]` -| hit_difficulty | (_optional_) Float. How hard is it to hit a given body part, assuming "owner" is hit. Higher number means good hits will veer towards this part, lower means this part is unlikely to be hit by inaccurate attacks. Formula is `chance *= pow(hit_roll, hit_difficulty)` (default: `0`) -| side | (_optional_) Which side this body part is on. Default both. -| stylish_bonus | (_optional_) Mood bonus associated with wearing fancy clothing on this part. (default: `0`) -| hot_morale_mod | (_optional_) Mood effect of being too hot on this part. (default: `0`) -| cold_morale_mod | (_optional_) Mood effect of being too cold on this part. (default: `0`) -| squeamish_penalty | (_optional_) Mood effect of wearing filthy clothing on this part. (default: `0`) -| bionic_slots | (_optional_) How many bionic slots does this part have. +| Identifier | Description | +| ----------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. | +| name | (_mandatory_) In-game name displayed. | +| accusative | (_mandatory_) Accusative form for this bodypart. | +| heading | (_mandatory_) How it's displayed in headings. | +| heading_multiple | (_optional_) Plural form of heading. (default: heading value) | +| hp_bar_ui_text | (_optional_) How it's displayed next to the hp bar in the panel. (default: empty string) | +| encumbrance_text | (_optional_) Description of effect when encumbered. (default: empty string) | +| main_part | (_optional_) What is the main part this one is attached to. (default: self) | +| base_hp | (_optional_) The amount of hp this part has before any modification. (default: `60`) | +| opposite_part | (_optional_) What is the opposite part ot this one in case of a pair. (default: self) | +| essential | (_optional_) Whether the character dies if this part drops to `0` HP. | +| hit_size | (_optional_) Float. Size of the body part when doing an unweighted selection. (default: `0.`) | +| hit_size_relative | (_optional_) Float. Hit sizes for attackers who are smaller, equal in size, and bigger. (default: `[ 0, 0, 0 ]` | +| hit_difficulty | (_optional_) Float. How hard is it to hit a given body part, assuming "owner" is hit. Higher number means good hits will veer towards this part, lower means this part is unlikely to be hit by inaccurate attacks. Formula is `chance *= pow(hit_roll, hit_difficulty)` (default: `0`) | +| side | (_optional_) Which side this body part is on. Default both. | +| stylish_bonus | (_optional_) Mood bonus associated with wearing fancy clothing on this part. (default: `0`) | +| hot_morale_mod | (_optional_) Mood effect of being too hot on this part. (default: `0`) | +| cold_morale_mod | (_optional_) Mood effect of being too cold on this part. (default: `0`) | +| squeamish_penalty | (_optional_) Mood effect of wearing filthy clothing on this part. (default: `0`) | +| bionic_slots | (_optional_) How many bionic slots does this part have. | ```C++ - { - "id": "torso", - "type": "body_part", - "name": "torso", - "accusative": { "ctxt": "bodypart_accusative", "str": "torso" }, - "heading": "Torso", - "heading_multiple": "Torso", - "hp_bar_ui_text": "TORSO", - "encumbrance_text": "Dodging and melee is hampered.", - "main_part": "torso", - "opposite_part": "torso", - "hit_size": 45, - "hit_size_relative": [ 20, 33.33, 36.57 ], - "hit_difficulty": 1, - "side": "both", - "legacy_id": "TORSO", - "stylish_bonus": 6, - "hot_morale_mod": 2, - "cold_morale_mod": 2, - "squeamish_penalty": 6, - "base_hp": 60, - "bionic_slots": 80 - } +{ + "id": "torso", + "type": "body_part", + "name": "torso", + "accusative": { "ctxt": "bodypart_accusative", "str": "torso" }, + "heading": "Torso", + "heading_multiple": "Torso", + "hp_bar_ui_text": "TORSO", + "encumbrance_text": "Dodging and melee is hampered.", + "main_part": "torso", + "opposite_part": "torso", + "hit_size": 45, + "hit_size_relative": [ 20, 33.33, 36.57 ], + "hit_difficulty": 1, + "side": "both", + "legacy_id": "TORSO", + "stylish_bonus": 6, + "hot_morale_mod": 2, + "cold_morale_mod": 2, + "squeamish_penalty": 6, + "base_hp": 60, + "bionic_slots": 80 +} ``` ### Bionics -| Identifier | Description -|--- |--- -| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. -| name | (_mandatory_) In-game name displayed. -| description | (_mandatory_) In-game description. -| flags | (_optional_) A list of flags. See JSON_FLAGS.md for supported values. -| act_cost | (_optional_) How many kJ it costs to activate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) -| deact_cost | (_optional_) How many kJ it costs to deactivate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) -| react_cost | (_optional_) How many kJ it costs over time to keep this bionic active, does nothing without a non-zero "time". Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) -| time | (_optional_) How long, when activated, between drawing cost. If 0, it draws power once. (default: `0`) -| upgraded_bionic | (_optional_) Bionic that can be upgraded by installing this one. -| available_upgrades | (_optional_) Upgrades available for this bionic, i.e. the list of bionics having this one referenced by `upgraded_bionic`. -| encumbrance | (_optional_) A list of body parts and how much this bionic encumber them. -| weight_capacity_bonus | (_optional_) Bonus to weight carrying capacity in grams, can be negative. Strings can be used - "5000 g" or "5 kg" (default: `0`) -| weight_capacity_modifier | (_optional_) Factor modifying base weight carrying capacity. (default: `1`) -| canceled_mutations | (_optional_) A list of mutations/traits that are removed when this bionic is installed (e.g. because it replaces the fault biological part). -| included_bionics | (_optional_) Additional bionics that are installed automatically when this bionic is installed. This can be used to install several bionics from one CBM item, which is useful as each of those can be activated independently. -| included | (_optional_) Whether this bionic is included with another. If true this bionic does not require a CBM item to be defined. (default: `false`) -| env_protec | (_optional_) How much environmental protection does this bionic provide on the specified body parts. -| bash_protec | (_optional_) How much bash protection does this bionic provide on the specified body parts. -| cut_protec | (_optional_) How much cut protection does this bionic provide on the specified body parts. -| bullet_protect | (_optional_) How much bullet protect does this bionic provide on the specified body parts. -| occupied_bodyparts | (_optional_) A list of body parts occupied by this bionic, and the number of bionic slots it take on those parts. -| capacity | (_optional_) Amount of power storage added by this bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) -| fuel_options | (_optional_) A list of fuel that this bionic can use to produce bionic power. -| is_remote_fueled | (_optional_) If true this bionic allows you to plug your power banks to an external power source (solar backpack, UPS, vehicle etc) via a cable. (default: `false`) -| fuel_capacity | (_optional_) Volume of fuel this bionic can store. -| fuel_efficiency | (_optional_) Fraction of fuel energy converted into power. (default: `0`) -| fuel_multiplier | (_optional_) Multiplies the amount of fuel when loading into the bionic (default: `1`) -| passive_fuel_efficiency | (_optional_) Fraction of fuel energy passively converted into power. Useful for CBM using PERPETUAL fuel like `muscle`, `wind` or `sun_light`. (default: `0`) -| exothermic_power_gen | (_optional_) If true this bionic emits heat when producing power. (default: `false`) -| coverage_power_gen_penalty | (_optional_) Fraction of coverage diminishing fuel_efficiency. Float between 0.0 and 1.0. (default: `nullopt`) -| power_gen_emission | (_optional_) `emit_id` of the field emitted by this bionic when it produces energy. Emit_ids are defined in `emit.json`. -| stat_bonus | (_optional_) List of passive stat bonus. Stat are designated as follow: "DEX", "INT", "STR", "PER". -| enchantments | (_optional_) List of enchantments applied by this CBM (see MAGIC.md for instructions on enchantment. NB: enchantments are not necessarily magic.) -| learned_spells | (_optional_) List of spells (with levels) you gain when installing this CBM, and lose when you uninstall this CBM. Spell classes are automatically gained. -| fake_item | (_optional_) ID of fake item used by this bionic. Mandatory for gun and weapon bionics. +| Identifier | Description | +| -------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. | +| name | (_mandatory_) In-game name displayed. | +| description | (_mandatory_) In-game description. | +| flags | (_optional_) A list of flags. See JSON_FLAGS.md for supported values. | +| act_cost | (_optional_) How many kJ it costs to activate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | +| deact_cost | (_optional_) How many kJ it costs to deactivate the bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | +| react_cost | (_optional_) How many kJ it costs over time to keep this bionic active, does nothing without a non-zero "time". Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | +| time | (_optional_) How long, when activated, between drawing cost. If 0, it draws power once. (default: `0`) | +| upgraded_bionic | (_optional_) Bionic that can be upgraded by installing this one. | +| available_upgrades | (_optional_) Upgrades available for this bionic, i.e. the list of bionics having this one referenced by `upgraded_bionic`. | +| encumbrance | (_optional_) A list of body parts and how much this bionic encumber them. | +| weight_capacity_bonus | (_optional_) Bonus to weight carrying capacity in grams, can be negative. Strings can be used - "5000 g" or "5 kg" (default: `0`) | +| weight_capacity_modifier | (_optional_) Factor modifying base weight carrying capacity. (default: `1`) | +| canceled_mutations | (_optional_) A list of mutations/traits that are removed when this bionic is installed (e.g. because it replaces the fault biological part). | +| included_bionics | (_optional_) Additional bionics that are installed automatically when this bionic is installed. This can be used to install several bionics from one CBM item, which is useful as each of those can be activated independently. | +| included | (_optional_) Whether this bionic is included with another. If true this bionic does not require a CBM item to be defined. (default: `false`) | +| env_protec | (_optional_) How much environmental protection does this bionic provide on the specified body parts. | +| bash_protec | (_optional_) How much bash protection does this bionic provide on the specified body parts. | +| cut_protec | (_optional_) How much cut protection does this bionic provide on the specified body parts. | +| bullet_protect | (_optional_) How much bullet protect does this bionic provide on the specified body parts. | +| occupied_bodyparts | (_optional_) A list of body parts occupied by this bionic, and the number of bionic slots it take on those parts. | +| capacity | (_optional_) Amount of power storage added by this bionic. Strings can be used "1 kJ"/"1000 J"/"1000000 mJ" (default: `0`) | +| fuel_options | (_optional_) A list of fuel that this bionic can use to produce bionic power. | +| is_remote_fueled | (_optional_) If true this bionic allows you to plug your power banks to an external power source (solar backpack, UPS, vehicle etc) via a cable. (default: `false`) | +| fuel_capacity | (_optional_) Volume of fuel this bionic can store. | +| fuel_efficiency | (_optional_) Fraction of fuel energy converted into power. (default: `0`) | +| fuel_multiplier | (_optional_) Multiplies the amount of fuel when loading into the bionic (default: `1`) | +| passive_fuel_efficiency | (_optional_) Fraction of fuel energy passively converted into power. Useful for CBM using PERPETUAL fuel like `muscle`, `wind` or `sun_light`. (default: `0`) | +| exothermic_power_gen | (_optional_) If true this bionic emits heat when producing power. (default: `false`) | +| coverage_power_gen_penalty | (_optional_) Fraction of coverage diminishing fuel_efficiency. Float between 0.0 and 1.0. (default: `nullopt`) | +| power_gen_emission | (_optional_) `emit_id` of the field emitted by this bionic when it produces energy. Emit_ids are defined in `emit.json`. | +| stat_bonus | (_optional_) List of passive stat bonus. Stat are designated as follow: "DEX", "INT", "STR", "PER". | +| enchantments | (_optional_) List of enchantments applied by this CBM (see MAGIC.md for instructions on enchantment. NB: enchantments are not necessarily magic.) | +| learned_spells | (_optional_) List of spells (with levels) you gain when installing this CBM, and lose when you uninstall this CBM. Spell classes are automatically gained. | +| fake_item | (_optional_) ID of fake item used by this bionic. Mandatory for gun and weapon bionics. | ```C++ { @@ -552,16 +576,17 @@ This section describes each json file and their contents. Each json has their ow } ``` -Bionics effects are defined in the code and new effects cannot be created through JSON alone. -When adding a new bionic, if it's not included with another one, you must also add the corresponding CBM item in `data/json/items/bionics.json`. Even for a faulty bionic. +Bionics effects are defined in the code and new effects cannot be created through JSON alone. When +adding a new bionic, if it's not included with another one, you must also add the corresponding CBM +item in `data/json/items/bionics.json`. Even for a faulty bionic. ### Dreams -| Identifier | Description -|--- |--- -| messages | List of potential dreams. -| category | Mutation category needed to dream. -| strength | Mutation category strength required (1 = 20-34, 2 = 35-49, 3 = 50+). +| Identifier | Description | +| ---------- | -------------------------------------------------------------------- | +| messages | List of potential dreams. | +| category | Mutation category needed to dream. | +| strength | Mutation category strength required (1 = 20-34, 2 = 35-49, 3 = 50+). | ```C++ { @@ -576,30 +601,29 @@ When adding a new bionic, if it's not included with another one, you must also a ### Disease -| Identifier | Description -|--- |--- -| id | Unique ID. Must be one continuous word, use underscores if necessary. -| min_duration | The minimum duration the disease can last. Uses strings "x m", "x s","x d". -| max_duration | The maximum duration the disease can last. -| min_intensity | The minimum intensity of the effect applied by the disease -| max_intensity | The maximum intensity of the effect. -| health_threshold | The amount of health above which one is immune to the disease. Must be between -200 and 200. (optional ) -| symptoms | The effect applied by the disease. -| affected_bodyparts | The list of bodyparts on which the effect is applied. (optional, default to num_bp) - +| Identifier | Description | +| ------------------ | -------------------------------------------------------------------------------------------------------- | +| id | Unique ID. Must be one continuous word, use underscores if necessary. | +| min_duration | The minimum duration the disease can last. Uses strings "x m", "x s","x d". | +| max_duration | The maximum duration the disease can last. | +| min_intensity | The minimum intensity of the effect applied by the disease | +| max_intensity | The maximum intensity of the effect. | +| health_threshold | The amount of health above which one is immune to the disease. Must be between -200 and 200. (optional ) | +| symptoms | The effect applied by the disease. | +| affected_bodyparts | The list of bodyparts on which the effect is applied. (optional, default to num_bp) | ```json - { - "type": "disease_type", - "id": "bad_food", - "min_duration": "6 m", - "max_duration": "1 h", - "min_intensity": 1, - "max_intensity": 1, - "affected_bodyparts": [ "TORSO" ], - "health_threshold": 100, - "symptoms": "foodpoison" - } +{ + "type": "disease_type", + "id": "bad_food", + "min_duration": "6 m", + "max_duration": "1 h", + "min_intensity": 1, + "max_intensity": 1, + "affected_bodyparts": ["TORSO"], + "health_threshold": 100, + "symptoms": "foodpoison" +} ``` ### Item Groups @@ -607,11 +631,11 @@ When adding a new bionic, if it's not included with another one, you must also a Item groups have been expanded, look at [the detailed docs](ITEM_SPAWN.md) to their new description. The syntax listed here is still valid. -| Identifier | Description -|--- |--- -| id | Unique ID. Must be one continuous word, use underscores if necessary -| items | List of potential item ID's. Chance of an item spawning is x/T, where X is the value linked to the specific item and T is the total of all item values in a group. -| groups | ?? +| Identifier | Description | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| id | Unique ID. Must be one continuous word, use underscores if necessary | +| items | List of potential item ID's. Chance of an item spawning is x/T, where X is the value linked to the specific item and T is the total of all item values in a group. | +| groups | ?? | ```C++ { @@ -632,13 +656,13 @@ The syntax listed here is still valid. When you sort your inventory by category, these are the categories that are displayed. -| Identifier | Description -|--- |--- -| id | Unique ID. Must be one continuous word, use underscores if necessary -| name | The name of the category. This is what shows up in-game when you open the inventory. -| zone | The corresponding loot_zone (see loot_zones.json) -| sort_rank | Used to sort categories when displaying. Lower values are shown first -| priority_zones | When set, items in this category will be sorted to the priority zone if the conditions are met. If the user does not have the priority zone in the zone manager, the items get sorted into zone set in the 'zone' property. It is a list of objects. Each object has 3 properties: ID: The id of a LOOT_ZONE (see LOOT_ZONES.json), filthy: boolean. setting this means filthy items of this category will be sorted to the priority zone, flags: array of flags +| Identifier | Description | +| -------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| id | Unique ID. Must be one continuous word, use underscores if necessary | +| name | The name of the category. This is what shows up in-game when you open the inventory. | +| zone | The corresponding loot_zone (see loot_zones.json) | +| sort_rank | Used to sort categories when displaying. Lower values are shown first | +| priority_zones | When set, items in this category will be sorted to the priority zone if the conditions are met. If the user does not have the priority zone in the zone manager, the items get sorted into zone set in the 'zone' property. It is a list of objects. Each object has 3 properties: ID: The id of a LOOT_ZONE (see LOOT_ZONES.json), filthy: boolean. setting this means filthy items of this category will be sorted to the priority zone, flags: array of flags | ```C++ { @@ -652,35 +676,36 @@ When you sort your inventory by category, these are the categories that are disp ### Materials -| Identifier | Description -|--- |--- -| `id` | Unique ID. Lowercase snake_case. Must be one continuous word, use underscores if necessary. -| `name` | In-game name displayed. -| `bash_resist` | How well a material resists bashing damage. -| `cut_resist` | How well a material resists cutting damage. -| `bullet_resist` | How well a material resists bullet damage. -| `acid_resist` | Ability of a material to resist acid. -| `elec_resist` | Ability of a material to resist electricity. -| `fire_resist` | Ability of a material to resist fire. -| `chip_resist` | Returns resistance to being damaged by attacks against the item itself. -| `bash_dmg_verb` | Verb used when material takes bashing damage. -| `cut_dmg_verb` | Verb used when material takes cutting damage. -| `dmg_adj` | Description added to damaged item in ascending severity. -| `dmg_adj` | Adjectives used to describe damage states of a material. -| `density` | Density of a material. -| `vitamins` | Vitamins in a material. Usually overridden by item specific values. -| `wind_resist` | Percentage 0-100. How effective this material is at stopping wind from getting through. Higher values are better. If none of the materials an item is made of specify a value, a default of 99 is assumed. -| `warmth_when_wet` | Percentage of warmth retained when fully drenched. Default is 0.2. -| `specific_heat_liquid` | Specific heat of a material when not frozen (J/(g K)). Default 4.186. -| `specific_heat_solid` | Specific heat of a material when frozen (J/(g K)). Default 2.108. -| `latent_heat` | Latent heat of fusion for a material (J/g). Default 334. -| `freeze_point` | Freezing point of this material (F). Default 32 F ( 0 C ). -| `edible` | Optional boolean. Default is false. -| `rotting` | Optional boolean. Default is false. -| `soft` | Optional boolean. Default is false. -| `reinforces` | Optional boolean. Default is false. - -There are six -resist parameters: acid, bash, chip, cut, elec, and fire. These are integer values; the default is 0 and they can be negative to take more damage. +| Identifier | Description | +| ---------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `id` | Unique ID. Lowercase snake_case. Must be one continuous word, use underscores if necessary. | +| `name` | In-game name displayed. | +| `bash_resist` | How well a material resists bashing damage. | +| `cut_resist` | How well a material resists cutting damage. | +| `bullet_resist` | How well a material resists bullet damage. | +| `acid_resist` | Ability of a material to resist acid. | +| `elec_resist` | Ability of a material to resist electricity. | +| `fire_resist` | Ability of a material to resist fire. | +| `chip_resist` | Returns resistance to being damaged by attacks against the item itself. | +| `bash_dmg_verb` | Verb used when material takes bashing damage. | +| `cut_dmg_verb` | Verb used when material takes cutting damage. | +| `dmg_adj` | Description added to damaged item in ascending severity. | +| `dmg_adj` | Adjectives used to describe damage states of a material. | +| `density` | Density of a material. | +| `vitamins` | Vitamins in a material. Usually overridden by item specific values. | +| `wind_resist` | Percentage 0-100. How effective this material is at stopping wind from getting through. Higher values are better. If none of the materials an item is made of specify a value, a default of 99 is assumed. | +| `warmth_when_wet` | Percentage of warmth retained when fully drenched. Default is 0.2. | +| `specific_heat_liquid` | Specific heat of a material when not frozen (J/(g K)). Default 4.186. | +| `specific_heat_solid` | Specific heat of a material when frozen (J/(g K)). Default 2.108. | +| `latent_heat` | Latent heat of fusion for a material (J/g). Default 334. | +| `freeze_point` | Freezing point of this material (F). Default 32 F ( 0 C ). | +| `edible` | Optional boolean. Default is false. | +| `rotting` | Optional boolean. Default is false. | +| `soft` | Optional boolean. Default is false. | +| `reinforces` | Optional boolean. Default is false. | + +There are six -resist parameters: acid, bash, chip, cut, elec, and fire. These are integer values; +the default is 0 and they can be negative to take more damage. ```C++ { @@ -716,25 +741,25 @@ There are six -resist parameters: acid, bash, chip, cut, elec, and fire. These a #### Group definition -| Identifier | Description -|--- |--- -| `name` | Unique ID. Must be one continuous word, use underscores if necessary. -| `default` | Default monster, automatically fills in any remaining spawn chances. -| `monsters` | To choose a monster for spawning, the game creates 1000 entries and picks one. Each monster will have a number of entries equal to it's "freq" and the default monster will fill in the remaining. See the table below for how to build the single monster definitions. -| `is_safe` | (bool) Check to not trigger safe-mode warning. -| `is_animal` | (bool) Check if that group has only normal animals. +| Identifier | Description | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `name` | Unique ID. Must be one continuous word, use underscores if necessary. | +| `default` | Default monster, automatically fills in any remaining spawn chances. | +| `monsters` | To choose a monster for spawning, the game creates 1000 entries and picks one. Each monster will have a number of entries equal to it's "freq" and the default monster will fill in the remaining. See the table below for how to build the single monster definitions. | +| `is_safe` | (bool) Check to not trigger safe-mode warning. | +| `is_animal` | (bool) Check if that group has only normal animals. | #### Monster definition -| Identifier | Description -|--- |--- -| `monster` | The monster's unique ID, eg. `"mon_zombie"`. -| `freq` | Chance of occurrence, x/1000. -| `cost_multiplier` | How many monsters each monster in this definition should count as, if spawning a limited number of monsters. -| `pack_size` | (_optional_) The minimum and maximum number of monsters in this group that should spawn together. (default: `[1,1]`) -| `conditions` | Conditions limit when monsters spawn. Valid options: `SUMMER`, `WINTER`, `AUTUMN`, `SPRING`, `DAY`, `NIGHT`, `DUSK`, `DAWN`. Multiple Time-of-day conditions (`DAY`, `NIGHT`, `DUSK`, `DAWN`) will be combined together so that any of those conditions makes the spawn valid. Multiple Season conditions (`SUMMER`, `WINTER`, `AUTUMN`, `SPRING`) will be combined together so that any of those conditions makes the spawn valid. -| `starts` | (_optional_) This entry becomes active after this time. (Measured in hours) -| `ends` | (_optional_) This entry becomes inactive after this time. (Measured in hours) +| Identifier | Description | +| ----------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `monster` | The monster's unique ID, eg. `"mon_zombie"`. | +| `freq` | Chance of occurrence, x/1000. | +| `cost_multiplier` | How many monsters each monster in this definition should count as, if spawning a limited number of monsters. | +| `pack_size` | (_optional_) The minimum and maximum number of monsters in this group that should spawn together. (default: `[1,1]`) | +| `conditions` | Conditions limit when monsters spawn. Valid options: `SUMMER`, `WINTER`, `AUTUMN`, `SPRING`, `DAY`, `NIGHT`, `DUSK`, `DAWN`. Multiple Time-of-day conditions (`DAY`, `NIGHT`, `DUSK`, `DAWN`) will be combined together so that any of those conditions makes the spawn valid. Multiple Season conditions (`SUMMER`, `WINTER`, `AUTUMN`, `SPRING`) will be combined together so that any of those conditions makes the spawn valid. | +| `starts` | (_optional_) This entry becomes active after this time. (Measured in hours) | +| `ends` | (_optional_) This entry becomes inactive after this time. (Measured in hours) | ```C++ { @@ -751,14 +776,14 @@ There are six -resist parameters: acid, bash, chip, cut, elec, and fire. These a ### Monster Factions -| Identifier | Description -|--- |--- -| `name` | Unique ID. Must be one continuous word, use underscores when necessary. -| `base_faction` | Optional base faction. Relations to other factions are inherited from it and relations of other factions to this one check this. -| `by_mood` | Be hostile towards this faction when angry, neutral otherwise. Default attitude to all other factions. -| `neutral` | Always be neutral towards this faction. -| `friendly` | Always be friendly towards this faction. By default a faction is friendly towards itself. -| `hate` | Always be hostile towards this faction. Will change target to monsters of this faction if available. +| Identifier | Description | +| -------------- | -------------------------------------------------------------------------------------------------------------------------------- | +| `name` | Unique ID. Must be one continuous word, use underscores when necessary. | +| `base_faction` | Optional base faction. Relations to other factions are inherited from it and relations of other factions to this one check this. | +| `by_mood` | Be hostile towards this faction when angry, neutral otherwise. Default attitude to all other factions. | +| `neutral` | Always be neutral towards this faction. | +| `friendly` | Always be friendly towards this faction. By default a faction is friendly towards itself. | +| `hate` | Always be hostile towards this faction. Will change target to monsters of this faction if available. | ```C++ { @@ -784,9 +809,12 @@ See MONSTERS.md ### Profession item substitution -Defines item replacements that are applied to the starting items based upon the starting traits. This allows for example to replace wool items with non-wool items when the characters starts with the wool allergy trait. +Defines item replacements that are applied to the starting items based upon the starting traits. +This allows for example to replace wool items with non-wool items when the characters starts with +the wool allergy trait. -If the JSON objects contains a "item" member, it defines a replacement for the given item, like this: +If the JSON objects contains a "item" member, it defines a replacement for the given item, like +this: ```C++ { @@ -798,12 +826,16 @@ If the JSON objects contains a "item" member, it defines a replacement for the g ] } ``` + This defines each item of type "sunglasses" shall be replaced with: + - an item "fitover_sunglasses" if the character has the "HYPEROPIC" trait, - two items "fitover_sunglasses" if the character has the "MYOPIC" trait. -If the JSON objects contains a "trait" member, it defines a replacement for multiple items that applies when the character has the given trait: -```C++ +If the JSON objects contains a "trait" member, it defines a replacement for multiple items that +applies when the character has the given trait: + +````C++ { "type": "profession_item_substitutions", "trait": "WOOLALLERGY", @@ -827,21 +859,25 @@ Professions are specified as JSON object with "type" member set to "profession": "id": "hunter", ... } -``` +```` The id member should be the unique id of the profession. The following properties (mandatory, except if noted otherwise) are supported: #### `description` + (string) The in-game description. #### `name` + (string or object with members "male" and "female") -The in-game name, either one gender-neutral string, or an object with gender specific names. Example: +The in-game name, either one gender-neutral string, or an object with gender specific names. +Example: + ```C++ "name": { "male": "Groom", @@ -850,25 +886,31 @@ The in-game name, either one gender-neutral string, or an object with gender spe ``` #### `points` + (integer) Point cost of profession. Positive values cost points and negative values grant points. #### `addictions` + (optional, array of addictions) List of starting addictions. Each entry in the list should be an object with the following members: + - "type": the string id of the addiction (see JSON_FLAGS.md), - "intensity": intensity (integer) of the addiction. Example: + ```C++ "addictions": [ { "type": "nicotine", "intensity": 10 } ] ``` -Mods can modify this list (requires `"edit-mode": "modify"`, see example) via "add:addictions" and "remove:addictions", removing requires only the addiction type. Example: +Mods can modify this list (requires `"edit-mode": "modify"`, see example) via "add:addictions" and +"remove:addictions", removing requires only the addiction type. Example: + ```C++ { "type": "profession", @@ -888,17 +930,22 @@ Mods can modify this list (requires `"edit-mode": "modify"`, see example) via "a (optional, array of skill levels) List of starting skills. Each entry in the list should be an object with the following members: + - "name": the string id of the skill (see skills.json), -- "level": level (integer) of the skill. This is added to the skill level that can be chosen in the character creation. +- "level": level (integer) of the skill. This is added to the skill level that can be chosen in the + character creation. Example: + ```C++ "skills": [ { "name": "archery", "level": 2 } ] ``` -Mods can modify this list (requires `"edit-mode": "modify"`, see example) via "add:skills" and "remove:skills", removing requires only the skill id. Example: +Mods can modify this list (requires `"edit-mode": "modify"`, see example) via "add:skills" and +"remove:skills", removing requires only the skill id. Example: + ```C++ { "type": "profession", @@ -911,16 +958,19 @@ Mods can modify this list (requires `"edit-mode": "modify"`, see example) via "a { "name": "computer", "level": 2 } ] } - ``` #### `items` (optional, object with optional members "both", "male" and "female") -Items the player starts with when selecting this profession. One can specify different items based on the gender of the character. Each lists of items should be an array of items ids, or pairs of item ids and snippet ids. Item ids may appear multiple times, in which case the item is created multiple times. The syntax for each of the three lists is identical. +Items the player starts with when selecting this profession. One can specify different items based +on the gender of the character. Each lists of items should be an array of items ids, or pairs of +item ids and snippet ids. Item ids may appear multiple times, in which case the item is created +multiple times. The syntax for each of the three lists is identical. Example: + ```C++ "items": { "both": [ @@ -939,9 +989,13 @@ Example: } ``` -This gives the player pants, two rocks, a t-shirt with the snippet id "allyourbase" (giving it a special description), socks and (depending on the gender) briefs or panties. +This gives the player pants, two rocks, a t-shirt with the snippet id "allyourbase" (giving it a +special description), socks and (depending on the gender) briefs or panties. -Mods can modify the lists of existing professions. This requires the "edit-mode" member with value "modify" (see example). Adding items to the lists can be done with via "add:both" / "add:male" / "add:female". It allows the same content (it allows adding items with snippet ids). Removing items is done via "remove:both" / "remove:male" / "remove:female", which may only contain items ids. +Mods can modify the lists of existing professions. This requires the "edit-mode" member with value +"modify" (see example). Adding items to the lists can be done with via "add:both" / "add:male" / +"add:female". It allows the same content (it allows adding items with snippet ids). Removing items +is done via "remove:both" / "remove:male" / "remove:female", which may only contain items ids. Example for mods: @@ -963,22 +1017,22 @@ Example for mods: } ``` -This mod removes one of the rocks (the other rock is still created), the t-shirt, adds a 2x4 item and gives female characters a t-shirt with the special snippet id. +This mod removes one of the rocks (the other rock is still created), the t-shirt, adds a 2x4 item +and gives female characters a t-shirt with the special snippet id. #### `pets` (optional, array of string mtype_ids ) -A list of strings, each is the same as a monster id -player will start with these as tamed pets. +A list of strings, each is the same as a monster id player will start with these as tamed pets. #### `vehicle` (optional, string vproto_id ) -A string, which is the same as a vehicle ( vproto_id ) -player will start with this as a nearby vehicle. -( it will find the nearest road and place it there, then mark it as "remembered" on the overmap ) +A string, which is the same as a vehicle ( vproto_id ) player will start with this as a nearby +vehicle. ( it will find the nearest road and place it there, then mark it as "remembered" on the +overmap ) #### `flags` @@ -1080,12 +1134,10 @@ Recipes represent both craft and uncraft (disassembly) recipes. #### Overlapping recipe component requirements -If recipes have requirements which overlap, this makes it more -difficult for the game to calculate whether it is possible to craft a recipe at -all. +If recipes have requirements which overlap, this makes it more difficult for the game to calculate +whether it is possible to craft a recipe at all. -For example, the survivor telescope recipe has the following requirements -(amongst others): +For example, the survivor telescope recipe has the following requirements (amongst others): ``` 1 high-quality lens @@ -1095,24 +1147,22 @@ AND These overlap because both list the high-quality lens. -A small amount of overlap (such as the above) can be handled, but if you have -too many component lists which overlap in too many ways, then you may see an -error during recipe finalization that your recipe is too complex. In this -case, the game may not be able to corectly predict whether it can be crafted. +A small amount of overlap (such as the above) can be handled, but if you have too many component +lists which overlap in too many ways, then you may see an error during recipe finalization that your +recipe is too complex. In this case, the game may not be able to corectly predict whether it can be +crafted. -To work around this issue, if you do not wish to simplify the recipe -requirements, then you can split your recipe into multiple steps. For -example, if we wanted to simplify the above survivor telescope recipe we could -introduce an intermediate item "survivor eyepiece", which requires one of -either lens, and then the telescope would require a high-quality lens and an -eyepiece. Overall, the requirements are the same, but neither recipe has any -overlap. +To work around this issue, if you do not wish to simplify the recipe requirements, then you can +split your recipe into multiple steps. For example, if we wanted to simplify the above survivor +telescope recipe we could introduce an intermediate item "survivor eyepiece", which requires one of +either lens, and then the telescope would require a high-quality lens and an eyepiece. Overall, the +requirements are the same, but neither recipe has any overlap. -For more details, see [this pull -request](https://github.com/CleverRaven/Cataclysm-DDA/pull/36657) and the -[related issue](https://github.com/CleverRaven/Cataclysm-DDA/issues/32311). +For more details, see [this pull request](https://github.com/CleverRaven/Cataclysm-DDA/pull/36657) +and the [related issue](https://github.com/CleverRaven/Cataclysm-DDA/issues/32311). ### Constructions + ```C++ "id": "constr_pit_spiked", // Identifier of the construction "group": "spike_pit", // Construction group, used to provide description and group related constructions in UI (e.g. different stages of some construction). @@ -1134,24 +1184,24 @@ request](https://github.com/CleverRaven/Cataclysm-DDA/pull/36657) and the "vehicle_start": false, // (Optional, default false) Whether it will create a vehicle (for hardcode purposes) "on_display": false, // (Optional, default true) Whether it will show in player's UI "dark_craftable": true, // (Optional, default false) Whether it can be constructed in dark - ``` ### Construction groups + ```C++ "id": "build_wooden_door", // Group identifier "name": "Build Wooden Door", // Description string displayed in the construction menu ``` ### Construction sequences -Constuction sequences are needed for automatic calculation of basecamp blueprint requirements. -Each construction sequence describes steps needed to construct specified terrain -or furniture on an empty dirt tile. -At any moment, only 1 construction sequence may be defined for any terrain or furniture. + +Constuction sequences are needed for automatic calculation of basecamp blueprint requirements. Each +construction sequence describes steps needed to construct specified terrain or furniture on an empty +dirt tile. At any moment, only 1 construction sequence may be defined for any terrain or furniture. For convenience, each non-blacklisted construction recipe that starts from an empty dirt tile -automatically generates a one-element-long construction sequence, but only as long as -there are no other such construction recipes that would produce the same sequence -and there isn't an explicitly defined sequence with same results. +automatically generates a one-element-long construction sequence, but only as long as there are no +other such construction recipes that would produce the same sequence and there isn't an explicitly +defined sequence with same results. ```C++ "id": "f_workbench", // Sequence identifier @@ -1167,30 +1217,29 @@ and there isn't an explicitly defined sequence with same results. ### Scent_types -| Identifier | Description -|--- |--- -| id | Unique ID. Must be one continuous word, use underscores if necessary. -| receptive_species | Species able to track this scent. Must use valid ids defined in `species.json` +| Identifier | Description | +| ----------------- | ------------------------------------------------------------------------------ | +| id | Unique ID. Must be one continuous word, use underscores if necessary. | +| receptive_species | Species able to track this scent. Must use valid ids defined in `species.json` | ```json - { - "type": "scent_type", - "id": "sc_flower", - "receptive_species": [ "MAMMAL", "INSECT", "MOLLUSK", "BIRD" ] - } +{ + "type": "scent_type", + "id": "sc_flower", + "receptive_species": ["MAMMAL", "INSECT", "MOLLUSK", "BIRD"] +} ``` ### Scores and Achievements -Scores are defined in two or three steps based on *events*. To see what events -exist and what data they contain, read [`event.h`](../src/event.h). +Scores are defined in two or three steps based on _events_. To see what events exist and what data +they contain, read [`event.h`](../src/event.h). -Each event contains a certain set of fields. Each field has a string key and a -`cata_variant` value. The fields should provide all the relevant information -about the event. +Each event contains a certain set of fields. Each field has a string key and a `cata_variant` value. +The fields should provide all the relevant information about the event. -For example, consider the `gains_skill_level` event. You can see this -specification for it in `event.h`: +For example, consider the `gains_skill_level` event. You can see this specification for it in +`event.h`: ```C++ template<> @@ -1205,39 +1254,37 @@ struct event_spec { ``` From this, you can see that this event type has three fields: -* `character`, with the id of the character gaining the level. -* `skill`, with the id of the skill gained. -* `new_level`, with the integer level newly acquired in that skill. - -Events are generated by the game when in-game circumstances dictate. These -events can be transformed and summarized in various ways. There are three -concepts involved: event streams, event statistics, and scores. - -* Each `event_type` defined by the game generates an event stream. -* Further event streams can be defined in json by applying an - `event_transformation` to an existing event stream. -* An `event_statistic` summarizes an event stream into a single value (usually - a number, but other types of value are possible). -* A `score` uses such a statistic to define an in-game score which players can - see. + +- `character`, with the id of the character gaining the level. +- `skill`, with the id of the skill gained. +- `new_level`, with the integer level newly acquired in that skill. + +Events are generated by the game when in-game circumstances dictate. These events can be transformed +and summarized in various ways. There are three concepts involved: event streams, event statistics, +and scores. + +- Each `event_type` defined by the game generates an event stream. +- Further event streams can be defined in json by applying an `event_transformation` to an existing + event stream. +- An `event_statistic` summarizes an event stream into a single value (usually a number, but other + types of value are possible). +- A `score` uses such a statistic to define an in-game score which players can see. #### `event_transformation` -An `event_transformation` can modify an event stream, producing another event -stream. +An `event_transformation` can modify an event stream, producing another event stream. -The input stream to be transformed is specified either as an `"event_type"`, to -use one of the built-in event type streams, or an `"event_transformation"`, -to use another json-defined transformed event stream. +The input stream to be transformed is specified either as an `"event_type"`, to use one of the +built-in event type streams, or an `"event_transformation"`, to use another json-defined transformed +event stream. Any or all of the following alterations can be made to the event stream: -* Add new fields to each event based on event field transformations. The event - field transformations can be found in - [`event_field_transformation.cpp`](../src/event_field_transformation.cpp). -* Filter events based on the values they contain to produce a stream containing - some subset of the input stream. -* Drop some fields which are not of interest in the output stream. +- Add new fields to each event based on event field transformations. The event field transformations + can be found in [`event_field_transformation.cpp`](../src/event_field_transformation.cpp). +- Filter events based on the values they contain to produce a stream containing some subset of the + input stream. +- Drop some fields which are not of interest in the output stream. Here are examples of each modification: @@ -1275,49 +1322,54 @@ Here are examples of each modification: #### `event_statistic` -As with `event_transformation`, an `event_statistic` requires an input event -stream. That input stream can be specified in the same was as for -`event_transformation`, via one of the following two entries: +As with `event_transformation`, an `event_statistic` requires an input event stream. That input +stream can be specified in the same was as for `event_transformation`, via one of the following two +entries: ```C++ "event_type" : "avatar_moves" // Events of this built-in type "event_transformation" : "moves_on_horse" // Events resulting from this json-defined transformation ``` -Then it specifies a particular `stat_type` and potentially additional details -as follows: +Then it specifies a particular `stat_type` and potentially additional details as follows: The number of events: + ```C++ "stat_type" : "count" ``` The sum of the numeric value in the specified field across all events: + ```C++ "stat_type" : "total" "field" : "damage" ``` The maximum of the numeric value in the specified field across all events: + ```C++ "stat_type" : "maximum" "field" : "damage" ``` The minimum of the numeric value in the specified field across all events: + ```C++ "stat_type" : "minimum" "field" : "damage" ``` -Assume there is only a single event to consider, and take the value of the -given field for that unique event: +Assume there is only a single event to consider, and take the value of the given field for that +unique event: + ```C++ "stat_type": "unique_value", "field": "avatar_id" ``` Regardless of `stat_type`, each `event_statistic` can also have: + ```C++ // Intended for use in describing scores and achievement requirements. "description": "Number of things" @@ -1325,15 +1377,14 @@ Regardless of `stat_type`, each `event_statistic` can also have: #### `score` -Scores simply associate a description to an event for formatting in tabulations -of scores. The `description` specifies a string which is expected to contain a -`%s` format specifier where the value of the statistic will be inserted. +Scores simply associate a description to an event for formatting in tabulations of scores. The +`description` specifies a string which is expected to contain a `%s` format specifier where the +value of the statistic will be inserted. -Note that even though most statistics yield an integer, you should still use -`%s`. +Note that even though most statistics yield an integer, you should still use `%s`. -If the underlying statistic has a description, then the score description is -optional. It defaults to ": ". +If the underlying statistic has a description, then the score description is optional. It defaults +to ": ". ```C++ "id": "score_headshots", @@ -1344,11 +1395,11 @@ optional. It defaults to ": ". #### `achievement` -Achievements are goals for the player to aspire to, in the usual sense of the -term as popularised in other games. +Achievements are goals for the player to aspire to, in the usual sense of the term as popularised in +other games. -An achievement is specified via requirements, each of which is a constraint on -an `event_statistic`. For example: +An achievement is specified via requirements, each of which is a constraint on an `event_statistic`. +For example: ```C++ { @@ -1366,8 +1417,8 @@ an `event_statistic`. For example: }, ``` -The `"is"` field must be `">="`, `"<="` or `"anything"`. When it is not -`"anything"` the `"target"` must be present, and must be an integer. +The `"is"` field must be `">="`, `"<="` or `"anything"`. When it is not `"anything"` the `"target"` +must be present, and must be an integer. There are further optional fields: @@ -1375,9 +1426,8 @@ There are further optional fields: "hidden_by": [ "other_achievement_id" ] ``` -Give a list of other achievement ids. This achievement will be hidden (i.e. -not appear in the achievements UI) until all of the achievements listed have -been completed. +Give a list of other achievement ids. This achievement will be hidden (i.e. not appear in the +achievements UI) until all of the achievements listed have been completed. Use this to prevent spoilers or to reduce clutter in the list of achievements. @@ -1385,45 +1435,41 @@ Use this to prevent spoilers or to reduce clutter in the list of achievements. "skill_requirements": [ { "skill": "archery", "is": ">=", "level": 5 } ] ``` -This allows a skill level requirement (either an upper or lower bound) on when -the achievement can be claimed. The `"skill"` field uses the id of a skill. - -Note that like `"time_constraint"` below achievements can only be captured when -a statistic listed in `"requirements"` changes. +This allows a skill level requirement (either an upper or lower bound) on when the achievement can +be claimed. The `"skill"` field uses the id of a skill. +Note that like `"time_constraint"` below achievements can only be captured when a statistic listed +in `"requirements"` changes. ```C++ "kill_requirements": [ { "faction": "ZOMBIE", "is": ">=", "count": 1 }, { "monster": "mon_sludge_crawler", "is": ">=", "count": 1 } ], ``` -This allows a kill requirement (either an upper or lower bound) on when -the achievement can be claimed. Can be defined with either `"faction"` or -`"monster"` as a target, using species ids from `species.json` or a -specific monster id. +This allows a kill requirement (either an upper or lower bound) on when the achievement can be +claimed. Can be defined with either `"faction"` or `"monster"` as a target, using species ids from +`species.json` or a specific monster id. -Only one of the `"monster"`/`"faction"` fields can be used per entry. If neither -are used, any monster will fulfill the requirements. +Only one of the `"monster"`/`"faction"` fields can be used per entry. If neither are used, any +monster will fulfill the requirements. NPCs cannot currently be defined as a target. -Note that like `"time_constraint"` below achievements can only be captured when -a statistic listed in `"requirements"` changes. +Note that like `"time_constraint"` below achievements can only be captured when a statistic listed +in `"requirements"` changes. ```C++ "time_constraint": { "since": "game_start", "is": "<=", "target": "1 minute" } ``` -This allows putting a time limit (either a lower or upper bound) on when the -achievement can be claimed. The `"since"` field can be either `"game_start"` -or `"cataclysm"`. The `"target"` describes an amount of time since that -reference point. +This allows putting a time limit (either a lower or upper bound) on when the achievement can be +claimed. The `"since"` field can be either `"game_start"` or `"cataclysm"`. The `"target"` describes +an amount of time since that reference point. -Note that achievements can only be captured when a statistic listed in their -requirements changes. So, if you want an achievement which would normally be -triggered by reaching some time threshold (such as "survived a certain amount -of time") then you must place some requirement alongside it to trigger it after -that time has passed. Pick some statistic which is likely to change often, and -add an `"anything"` constraint on it. For example: +Note that achievements can only be captured when a statistic listed in their requirements changes. +So, if you want an achievement which would normally be triggered by reaching some time threshold +(such as "survived a certain amount of time") then you must place some requirement alongside it to +trigger it after that time has passed. Pick some statistic which is likely to change often, and add +an `"anything"` constraint on it. For example: ```C++ { @@ -1435,8 +1481,8 @@ add an `"anything"` constraint on it. For example: }, ``` -This is a simple "survive a day" but is triggered by waking up, so it will be -completed when you wake up for the first time after 24 hours into the game. +This is a simple "survive a day" but is triggered by waking up, so it will be completed when you +wake up for the first time after 24 hours into the game. ### Skills @@ -1552,7 +1598,6 @@ completed when you wake up for the first time after 24 hours into the game. ### Vehicle Groups - ```C++ "id":"city_parked", // Unique ID. Must be one continuous word, use underscores if necessary "vehicles":[ // List of potential vehicle ID's. Chance of a vehicle spawning is X/T, where @@ -1635,6 +1680,7 @@ Vehicle components when installed on a vehicle. ``` ### Vehicle Placement + ```C++ "id":"road_straight_wrecks", // Unique ID. Must be one continuous word, use underscores if necessary "locations":[ { // List of potential vehicle locations. When this placement is used, one of those locations will be chosen at random. @@ -1665,6 +1711,7 @@ Vehicle components when installed on a vehicle. ``` ### Vehicles + See also VEHICLE_JSON.md ```C++ @@ -1713,7 +1760,7 @@ See also VEHICLE_JSON.md "rigid": false, // For non-rigid items volume (and for worn items encumbrance) increases proportional to contents "insulation": 1, // (Optional, default = 1) If container or vehicle part, how much insulation should it provide to the contents "price": 100, // Used when bartering with NPCs. For stackable items (ammo, comestibles) this is the price for stack_size charges. Can use string "cent" "USD" or "kUSD". -"price_post": "1 USD", // Same as price but represent value post cataclysm. Can use string "cent" "USD" or "kUSD". +"price_postapoc": "1 USD", // Same as price but represent value post cataclysm. Can use string "cent" "USD" or "kUSD". "material": ["COTTON"], // Material types, can be as many as you want. See materials.json for possible options "weapon_category": [ "WEAPON_CAT1" ], // (Optional) Weapon categories this item is in for martial arts. "cutting": 0, // (Optional, default = 0) Cutting damage caused by using it as a melee weapon. This value cannot be negative. @@ -1801,7 +1848,9 @@ Armor can be defined like this: "power_armor" : false, // If this is a power armor item (those are special). "valid_mods" : ["steel_padded"] // List of valid clothing mods. Note that if the clothing mod doesn't have "restricted" listed, this isn't needed. ``` + Alternately, every item (book, tool, gun, even food) can be used as armor if it has armor_data: + ```C++ "type" : "TOOL", // Or any other item type ... // same entries as for the type (e.g. same entries as for any tool), @@ -1818,6 +1867,7 @@ Alternately, every item (book, tool, gun, even food) can be used as armor if it ``` ### Pet Armor + Pet armor can be defined like this: ```C++ @@ -1832,7 +1882,9 @@ Pet armor can be defined like this: "min_pet_vol: // the minimum volume of the pet that will fit into this armor. Volume in ml and L can be used - "50 ml" or "2 L". "power_armor" : false, // If this is a power armor item (those are special). ``` + Alternately, every item (book, tool, gun, even food) can be used as armor if it has armor_data: + ```C++ "type" : "TOOL", // Or any other item type ... // same entries as for the type (e.g. same entries as for any tool), @@ -1863,7 +1915,9 @@ Books can be defined like this: "chapters" : 4, // Number of chapters (for fun only books), each reading "consumes" a chapter. Books with no chapters left are less fun (because the content is already known to the character). "required_level" : 2 // Minimum skill level required to learn ``` + Alternately, every item (tool, gun, even food) can be used as book if it has book_data: + ```C++ "type" : "TOOL", // Or any other item type ... // same entries as for the type (e.g. same entries as for any tool), @@ -1879,22 +1933,32 @@ Alternately, every item (tool, gun, even food) can be used as book if it has boo } ``` -Since many book names are proper names, it's often necessary to explicitly specify -the plural forms. The following is the game's convention on plural names of books: +Since many book names are proper names, it's often necessary to explicitly specify the plural forms. +The following is the game's convention on plural names of books: 1. For non-periodical books (textbooks, manuals, spellbooks, etc.), - 1. If the book's singular name is a proper name, then the plural name is `copies of (singular name)`. For example, the plural name of `Lessons for the Novice Bowhunter` is `copies of Lessons for the Novice Bowhunter`. - 2. Otherwise, the plural name is the usual plural of the singular name. For example, the plural name of `tactical baton defense manual` is `tactical baton defense manuals` + 1. If the book's singular name is a proper name, then the plural name is + `copies of (singular name)`. For example, the plural name of + `Lessons for the Novice Bowhunter` is `copies of Lessons for the Novice Bowhunter`. + 2. Otherwise, the plural name is the usual plural of the singular name. For example, the plural + name of `tactical baton defense manual` is `tactical baton defense manuals` 2. For periodicals (magazines and journals), - 1. If the periodical's singular name is a proper name, and doesn't end with "Magazine", "Weekly", "Monthly", etc., the plural name is `issues of (singular name)`. For example, the plural name of `Archery for Kids` is `issues of Archery for Kids`. - 2. Otherwise, the periodical's plural name is the usual plural of the singular name. For example, the plural name of `Crafty Crafter's Quarterly` is `Crafty Crafter's Quarterlies`. + 1. If the periodical's singular name is a proper name, and doesn't end with "Magazine", "Weekly", + "Monthly", etc., the plural name is `issues of (singular name)`. For example, the plural name + of `Archery for Kids` is `issues of Archery for Kids`. + 2. Otherwise, the periodical's plural name is the usual plural of the singular name. For example, + the plural name of `Crafty Crafter's Quarterly` is `Crafty Crafter's Quarterlies`. 3. For board games (represented internally as book items), - 1. If the board game's singular name is a proper name, the plural is `sets of (singular name)`. For example, the plural name of `Picturesque` is `sets of Picturesque`. - 2. Otherwise the plural name is the usual plural. For example, the plural of `deck of cards` is `decks of cards`. + 1. If the board game's singular name is a proper name, the plural is `sets of (singular name)`. + For example, the plural name of `Picturesque` is `sets of Picturesque`. + 2. Otherwise the plural name is the usual plural. For example, the plural of `deck of cards` is + `decks of cards`. #### Conditional Naming -The `conditional_names` field allows defining alternate names for items that will be displayed instead of (or in addition to) the default name, when specific conditions are met. Take the following (incomplete) definition for `sausage` as an example of the syntax: +The `conditional_names` field allows defining alternate names for items that will be displayed +instead of (or in addition to) the default name, when specific conditions are met. Take the +following (incomplete) definition for `sausage` as an example of the syntax: ```json { @@ -1914,35 +1978,49 @@ The `conditional_names` field allows defining alternate names for items that wil } ``` -You can list as many conditional names for a given item as you want. Each conditional name must consist of 3 elements: +You can list as many conditional names for a given item as you want. Each conditional name must +consist of 3 elements: + 1. The condition type: - - `COMPONENT_ID` searches all the components of the item (and all of *their* components, and so on) for an item with the condition string in their ID. The ID only needs to *contain* the condition, not match it perfectly (though it is case sensitive). For example, supplying a condition `mutant` would match `mutant_meat`. - - `FLAG` which checks if an item has the specified flag (exact match). + - `COMPONENT_ID` searches all the components of the item (and all of _their_ components, and so + on) for an item with the condition string in their ID. The ID only needs to _contain_ the + condition, not match it perfectly (though it is case sensitive). For example, supplying a + condition `mutant` would match `mutant_meat`. + - `FLAG` which checks if an item has the specified flag (exact match). 2. The condition you want to look for. -3. The name to use if a match is found. Follows all the rules of a standard `name` field, with valid keys being `str`, `str_pl`, and `ctxt`. You may use %s here, which will be replaced by the name of the item. Conditional names defined prior to this one are taken into account. +3. The name to use if a match is found. Follows all the rules of a standard `name` field, with valid + keys being `str`, `str_pl`, and `ctxt`. You may use %s here, which will be replaced by the name + of the item. Conditional names defined prior to this one are taken into account. -So, in the above example, if the sausage is made from mutant humanoid meat, and therefore both has the `CANNIBALISM` flag, *and* has a component with `mutant` in its ID: -1. First, the item name is entirely replaced with "Mannwurst" if singular, or "Mannwursts" if plural. -2. Next, it is replaced by "sinister %s", but %s is replaced with the name as it was before this step, resulting in "sinister Mannwurst" or "sinister Mannwursts". +So, in the above example, if the sausage is made from mutant humanoid meat, and therefore both has +the `CANNIBALISM` flag, _and_ has a component with `mutant` in its ID: -NB: If `"str": "sinister %s"` was specified instead of `"str_sp": "sinister %s"`, the plural form would be automatically created as "sinister %ss", which would become "sinister Mannwurstss" which is of course one S too far. Rule of thumb: If you are using %s in the name, always specify an identical plural form unless you know exactly what you're doing! +1. First, the item name is entirely replaced with "Mannwurst" if singular, or "Mannwursts" if + plural. +2. Next, it is replaced by "sinister %s", but %s is replaced with the name as it was before this + step, resulting in "sinister Mannwurst" or "sinister Mannwursts". +NB: If `"str": "sinister %s"` was specified instead of `"str_sp": "sinister %s"`, the plural form +would be automatically created as "sinister %ss", which would become "sinister Mannwurstss" which is +of course one S too far. Rule of thumb: If you are using %s in the name, always specify an identical +plural form unless you know exactly what you're doing! #### Color Key When adding a new book, please use this color key: -* Magazines: `pink` -* “Paperbacks” Short enjoyment books (including novels): `light_cyan` -* “Hardbacks” Long enjoyment books (including novels): `light_blue` -* “Small textbook” Beginner level textbooks, guides and martial arts books: `green` -* “Large textbook” Advanced level textbooks and advanced guides: `blue` -* Religious books: `dark_gray` -* “Printouts” (including spiral-bound, binders, and similar) Technical documents, (technical?) protocols, (lab) journals, personal diaries: `light_green` -* Other reading material/non-books (use only if every other category does not apply): `light_gray` +- Magazines: `pink` +- “Paperbacks” Short enjoyment books (including novels): `light_cyan` +- “Hardbacks” Long enjoyment books (including novels): `light_blue` +- “Small textbook” Beginner level textbooks, guides and martial arts books: `green` +- “Large textbook” Advanced level textbooks and advanced guides: `blue` +- Religious books: `dark_gray` +- “Printouts” (including spiral-bound, binders, and similar) Technical documents, (technical?) + protocols, (lab) journals, personal diaries: `light_green` +- Other reading material/non-books (use only if every other category does not apply): `light_gray` -A few exceptions to this color key may apply, for example for books that don’t are what they seem to be. -Never use `yellow` and `red`, those colors are reserved for sounds and infrared vision. +A few exceptions to this color key may apply, for example for books that don’t are what they seem to +be. Never use `yellow` and `red`, those colors are reserved for sounds and infrared vision. ####CBMs @@ -1998,7 +2076,9 @@ CBMs can be defined like this: "watertight": false, // Can hold liquids, this is a required for it to be used for liquids. (optional, default: false) "preserves": false, // Contents do not spoil. (optional, default: false) ``` + Alternately, every item can be used as container: + ```C++ "type": "ARMOR", // Any type is allowed here ... // same data as for the type @@ -2006,8 +2086,10 @@ Alternately, every item can be used as container: "contains": 200, } ``` -This defines a armor (you need to add all the armor specific entries), but makes it usable as container. -It could also be written as a generic item ("type": "GENERIC") with "armor_data" and "container_data" entries. + +This defines a armor (you need to add all the armor specific entries), but makes it usable as +container. It could also be written as a generic item ("type": "GENERIC") with "armor_data" and +"container_data" entries. ### Melee @@ -2029,44 +2111,44 @@ It could also be written as a generic item ("type": "GENERIC") with "armor_data" #### Melee `Weapon_category` -| Weapon Category | Description -| --- | --- -| FIST_WEAPONS | Handheld weapons used to supplement fists in martial arts. -| --- | --- -| KNIVES | Short blade fixed onto a handle, for cutting or as weapon. -| SHORT_SWORDS | One handed sword of length between a large knife and a 'proper' sword. -| 1H_SWORDS | Sword meant to be wielded with one hand. -| 2H_SWORDS | Sword meant to be wielded with both hands. -| DUELING_SWORDS | Swords with thin profiles typically meant for stabbing. -| BIONIC_SWORDS | Swords integrated into the body via bionics. -| --- | --- -| SAPS | Very short length of typically flexible material, with a weighted tip. -| BATONS | Thin, balanced rod of strong material. -| TONFAS | Unique looking T-shaped baton believed to originate from China. -| CLUBS | Rod with a thicker striking head. May be one or two-handed. -| QUARTERSTAVES | Long pole wielded with both hands. -| MACES | Short one-handed weapon with a striking head firmly attached to a short handle. -| MORNINGSTARS | Typically two-handed weapon with a striking head firmly attached to a long handle. -| FLAILS | Striking head attached to handle by flexible rope/chain. -| 1H_HAMMERS | Hammers meant to be wielded with a single hand. -| 2H_HAMMERS | Hammers meant to be wielded with both hands. -| --- | --- -| HAND_AXES | Axe with a short handle, typically wielded in one hand, ocassionally thrown. -| 1H_AXES | Axes meant to be wielded with one hand, typically with a handle longer than the handaxe. -| 2H_AXES | Axes meant to be wielded with two hands. -| --- | --- -| WHIPS | Flexible tool used to strike at range. -| --- | --- -| HOOKED_POLES | Polearm with hooked end (Like a shepherd's crook) -| SPEARS | Polearm with a long shaft and a sharp tip made of hard material. -| PIKES | Very long spear that can only be wielded in two hands, very unwieldy. -| GLAIVES | Polearm with a single-edged blade mounted on the end. - -| Weapon Styles | Description -| --- | --- -| MEDIEVAL_SWORDS | Swords associated with European culture. -| JAPANESE_SWORDS | Swords associated with Japanese culture. -| BIONIC_WEAPONRY | Weapons integrated into the body via bionics. +| Weapon Category | Description | +| --------------- | ---------------------------------------------------------------------------------------- | +| FIST_WEAPONS | Handheld weapons used to supplement fists in martial arts. | +| --- | --- | +| KNIVES | Short blade fixed onto a handle, for cutting or as weapon. | +| SHORT_SWORDS | One handed sword of length between a large knife and a 'proper' sword. | +| 1H_SWORDS | Sword meant to be wielded with one hand. | +| 2H_SWORDS | Sword meant to be wielded with both hands. | +| DUELING_SWORDS | Swords with thin profiles typically meant for stabbing. | +| BIONIC_SWORDS | Swords integrated into the body via bionics. | +| --- | --- | +| SAPS | Very short length of typically flexible material, with a weighted tip. | +| BATONS | Thin, balanced rod of strong material. | +| TONFAS | Unique looking T-shaped baton believed to originate from China. | +| CLUBS | Rod with a thicker striking head. May be one or two-handed. | +| QUARTERSTAVES | Long pole wielded with both hands. | +| MACES | Short one-handed weapon with a striking head firmly attached to a short handle. | +| MORNINGSTARS | Typically two-handed weapon with a striking head firmly attached to a long handle. | +| FLAILS | Striking head attached to handle by flexible rope/chain. | +| 1H_HAMMERS | Hammers meant to be wielded with a single hand. | +| 2H_HAMMERS | Hammers meant to be wielded with both hands. | +| --- | --- | +| HAND_AXES | Axe with a short handle, typically wielded in one hand, ocassionally thrown. | +| 1H_AXES | Axes meant to be wielded with one hand, typically with a handle longer than the handaxe. | +| 2H_AXES | Axes meant to be wielded with two hands. | +| --- | --- | +| WHIPS | Flexible tool used to strike at range. | +| --- | --- | +| HOOKED_POLES | Polearm with hooked end (Like a shepherd's crook) | +| SPEARS | Polearm with a long shaft and a sharp tip made of hard material. | +| PIKES | Very long spear that can only be wielded in two hands, very unwieldy. | +| GLAIVES | Polearm with a single-edged blade mounted on the end. | + +| Weapon Styles | Description | +| --------------- | --------------------------------------------- | +| MEDIEVAL_SWORDS | Swords associated with European culture. | +| JAPANESE_SWORDS | Swords associated with Japanese culture. | +| BIONIC_WEAPONRY | Weapons integrated into the body via bionics. | ### Gun @@ -2099,7 +2181,9 @@ Guns can be defined like this: "barrel_length": "30 mL", // Amount of volume lost when the barrel is sawn. Approximately 250 ml per inch is a decent approximation. "valid_mod_locations": [ [ "accessories", 4 ], [ "grip", 1 ] ], // The valid locations for gunmods and the mount of slots for that location. ``` + Alternately, every item (book, tool, armor, even food) can be used as gun if it has gun_data: + ```json "type": "TOOL", // Or any other item type ... // same entries as for the type (e.g. same entries as for any tool), @@ -2112,38 +2196,38 @@ Alternately, every item (book, tool, armor, even food) can be used as gun if it #### Ranged `Weapon_category` -| Weapon Category | Description -| --- | --- -| BOWS | Elastic launching device for long-shafted projectiles. -| S_XBOWS | Elastic launching device mounted on a frame to be triggered, pistol sized. -| M_XBOWS | Elastic launching device mounted on a frame to be triggered. -| SLINGSHOTS | Elastic, handheld launching device typically used for small round projectiles. -| SLINGS | Projectile weapon using a cradle connected to two retention cords, used to fling blunt projectiles. -| --- | --- -| PISTOLS | Handgun with a chamber integral to the gun barrel. In-game, any handgun that isn't a revolver goes here. -| REVOLVERS | Repeating handgun with a revolving cylinder containing multiple chambers. -| SUBMACHINE_GUNS | Magazine fed automatic carbine designed to fire handgun cartridges. -| RIFLES | Long barrelled firearms designed for more accurate shooting. -| MACHINE_GUNS | Fully automatic autoloading firearm designed for sustained fire. -| GATLING_GUNS | Rapid firing multi barrel firearm. -| SHOTGUNS | Long barreled firearm generally designed to fire shotshells. -| --- | --- -| GRENADE_LAUNCHERS | Firearm designed to propel large caliber projectile typically loaded with warhead of some kind (smoke, gas, explosive, etc) -| ROCKET_LAUNCHERS | Firearm that propels unguided, rocket-propelled projectile. -| --- | --- -| FLAMETHROWERS | Ranged incendiary device designed to propel a controllable jet of fire. -| WATER_CANNONS | It fires water at your enemies. -| SPRAY_GUNS | It spews chemicals at your enemies. - -| Action category | Description -| --- | --- -| 1SHOT | Ranged weapon with at least one barrel but no loading system/magazine. -| AUTOLOADING | Ranged weapon with autoloading mechanisms like blowback, gas-operated, or recoil operated systems. -| MANUAL_ACTION | Ranged weapon using manual actions like bolt/pump/lever. -| ENERGY_WEAPONS | Weapon designed to utilize focused energy (sonic, electromagnetic waves, particle beams, etc). Both Ranged/Melee. -| MAGNETIC | Weapon that propels payload via electromagnetism. -| PNEUMATIC | Ranged weapon that propels payload via compressed air. -| ELASTIC | Ranged weapon that propels payload via elastic band. +| Weapon Category | Description | +| ----------------- | --------------------------------------------------------------------------------------------------------------------------- | +| BOWS | Elastic launching device for long-shafted projectiles. | +| S_XBOWS | Elastic launching device mounted on a frame to be triggered, pistol sized. | +| M_XBOWS | Elastic launching device mounted on a frame to be triggered. | +| SLINGSHOTS | Elastic, handheld launching device typically used for small round projectiles. | +| SLINGS | Projectile weapon using a cradle connected to two retention cords, used to fling blunt projectiles. | +| --- | --- | +| PISTOLS | Handgun with a chamber integral to the gun barrel. In-game, any handgun that isn't a revolver goes here. | +| REVOLVERS | Repeating handgun with a revolving cylinder containing multiple chambers. | +| SUBMACHINE_GUNS | Magazine fed automatic carbine designed to fire handgun cartridges. | +| RIFLES | Long barrelled firearms designed for more accurate shooting. | +| MACHINE_GUNS | Fully automatic autoloading firearm designed for sustained fire. | +| GATLING_GUNS | Rapid firing multi barrel firearm. | +| SHOTGUNS | Long barreled firearm generally designed to fire shotshells. | +| --- | --- | +| GRENADE_LAUNCHERS | Firearm designed to propel large caliber projectile typically loaded with warhead of some kind (smoke, gas, explosive, etc) | +| ROCKET_LAUNCHERS | Firearm that propels unguided, rocket-propelled projectile. | +| --- | --- | +| FLAMETHROWERS | Ranged incendiary device designed to propel a controllable jet of fire. | +| WATER_CANNONS | It fires water at your enemies. | +| SPRAY_GUNS | It spews chemicals at your enemies. | + +| Action category | Description | +| --------------- | ----------------------------------------------------------------------------------------------------------------- | +| 1SHOT | Ranged weapon with at least one barrel but no loading system/magazine. | +| AUTOLOADING | Ranged weapon with autoloading mechanisms like blowback, gas-operated, or recoil operated systems. | +| MANUAL_ACTION | Ranged weapon using manual actions like bolt/pump/lever. | +| ENERGY_WEAPONS | Weapon designed to utilize focused energy (sonic, electromagnetic waves, particle beams, etc). Both Ranged/Melee. | +| MAGNETIC | Weapon that propels payload via electromagnetism. | +| PNEUMATIC | Ranged weapon that propels payload via compressed air. | +| ELASTIC | Ranged weapon that propels payload via elastic band. | ### Gunmod @@ -2170,7 +2254,10 @@ Gun mods can be defined like this: "reload_modifier": -10, // Optional field increasing or decreasing base gun reload time in percent "min_str_required_mod": 14, // Optional field increasing or decreasing minimum strength required to use gun ``` -Alternately, every item (book, tool, armor, even food) can be used as a gunmod if it has gunmod_data: + +Alternately, every item (book, tool, armor, even food) can be used as a gunmod if it has +gunmod_data: + ``` "type": "TOOL", // Or any other item type ... // same entries as for the type (e.g. same entries as for any tool), @@ -2182,6 +2269,7 @@ Alternately, every item (book, tool, armor, even food) can be used as a gunmod i ``` ### Batteries + ```C++ "type": "BATTERY", // Defines this as a BATTERY ... // Same entries as above for the generic item @@ -2222,7 +2310,8 @@ Alternately, every item (book, tool, armor, even food) can be used as a gunmod i ### Seed Data -Every item type can have optional seed data, if the item has seed data, it's considered a seed and can be planted: +Every item type can have optional seed data, if the item has seed data, it's considered a seed and +can be planted: ```C++ "seed_data" : { @@ -2239,7 +2328,8 @@ Every item type can have optional seed data, if the item has seed data, it's con ### Brewing Data -Every item type can have optional brewing data, if the item has brewing data, it can be placed in a vat and will ferment into a different item type. +Every item type can have optional brewing data, if the item has brewing data, it can be placed in a +vat and will ferment into a different item type. Currently only vats can only accept and produce liquid items. @@ -2252,8 +2342,7 @@ Currently only vats can only accept and produce liquid items. ### Relic Data -Defines various (semi-)magical properties of items. -See RELICS.md for +Defines various (semi-)magical properties of items. See RELICS.md for ### Artifact Data @@ -2305,6 +2394,7 @@ Possible values (see src/enums.h for an up-to-date list): - `AEP_SICK` Decreases health over time #### `effects_worn` + (optional, default: empty list) Effects of the artifact when it's worn (it must be an armor item to be worn). @@ -2323,7 +2413,8 @@ Possible values are the same as for effects_carried. (optional, default: empty list) -Effects of the artifact when it's activated (which require it to have a `"use_action": "ARTIFACT"` and it must have a non-zero max_charges value). +Effects of the artifact when it's activated (which require it to have a `"use_action": "ARTIFACT"` +and it must have a non-zero max_charges value). Possible values (see src/artifact.h for an up-to-date list): @@ -2373,9 +2464,12 @@ Every item type can have software data, it does not have any behavior: ### Fuel data -Every item type can have fuel data that determines how much horse power it produces per unit consumed. Currently, gasses and plasmas cannot really be fuels. +Every item type can have fuel data that determines how much horse power it produces per unit +consumed. Currently, gasses and plasmas cannot really be fuels. -If a fuel has the PERPETUAL flag, engines powered by it never use any fuel. This is primarily intended for the muscle pseudo-fuel, but mods may take advantage of it to make perpetual motion machines. +If a fuel has the PERPETUAL flag, engines powered by it never use any fuel. This is primarily +intended for the muscle pseudo-fuel, but mods may take advantage of it to make perpetual motion +machines. ```C++ "fuel" : { @@ -2397,7 +2491,9 @@ If a fuel has the PERPETUAL flag, engines powered by it never use any fuel. Thi ### Use Actions -The contents of use_action fields can either be a string indicating a built-in function to call when the item is activated (defined in iuse.cpp), or one of several special definitions that invoke a more structured function. +The contents of use_action fields can either be a string indicating a built-in function to call when +the item is activated (defined in iuse.cpp), or one of several special definitions that invoke a +more structured function. ```C++ "use_action": { @@ -2650,11 +2746,16 @@ The contents of use_action fields can either be a string indicating a built-in f ### Random Descriptions -Any item with a "snippet_category" entry will have random descriptions, based on that snippet category: +Any item with a "snippet_category" entry will have random descriptions, based on that snippet +category: + ``` "snippet_category": "newspaper", ``` -The item descriptions are taken from snippets, which can be specified like this (the value of category must match the snippet_category in the item definition): + +The item descriptions are taken from snippets, which can be specified like this (the value of +category must match the snippet_category in the item definition): + ```C++ { "type" : "snippet", @@ -2663,7 +2764,9 @@ The item descriptions are taken from snippets, which can be specified like this "text": "your flavor text" } ``` + or several snippets at once: + ```C++ { "type" : "snippet", @@ -2677,14 +2780,18 @@ or several snippets at once: "text": [ "your flavor text", "another flavor text", "more flavor" ] } ``` -Multiple snippets for the same category are possible and actually recommended. The game will select a random one for each item of that type. + +Multiple snippets for the same category are possible and actually recommended. The game will select +a random one for each item of that type. One can also put the snippets directly in the item definition: + ``` "snippet_category": [ "text 1", "text 2", "text 3" ], ``` -This will automatically create a snippet category specific to that item and populate that category with the given snippets. -The format also support snippet ids like above. + +This will automatically create a snippet category specific to that item and populate that category +with the given snippets. The format also support snippet ids like above. # `json/` JSONs @@ -2747,35 +2854,41 @@ Should always be `harvest` to mark the object as a harvest definition. #### `message` -Optional message to be printed when a creature using the harvest definition is butchered. May be omitted from definition. +Optional message to be printed when a creature using the harvest definition is butchered. May be +omitted from definition. #### `entries` -Array of dictionaries defining possible items produced on butchering and their likelihood of being produced. -`drop` value should be the `id` string of the item to be produced. +Array of dictionaries defining possible items produced on butchering and their likelihood of being +produced. `drop` value should be the `id` string of the item to be produced. -`type` value should be a string with the associated body part the item comes from. - Acceptable values are as follows: - `flesh`: the "meat" of the creature. - `offal`: the "organs" of the creature. these are removed when field dressing. - `skin`: the "skin" of the creature. this is what is ruined while quartering. - `bone`: the "bones" of the creature. you will get some amount of these from field dressing, and the rest of them from butchering the carcass. - `bionic`: an item gained by dissecting the creature. not restricted to CBMs. - `bionic_group`: an item group that will give an item by dissecting a creature. not restricted to groups containing CBMs. +`type` value should be a string with the associated body part the item comes from. Acceptable values +are as follows: `flesh`: the "meat" of the creature. `offal`: the "organs" of the creature. these +are removed when field dressing. `skin`: the "skin" of the creature. this is what is ruined while +quartering. `bone`: the "bones" of the creature. you will get some amount of these from field +dressing, and the rest of them from butchering the carcass. `bionic`: an item gained by dissecting +the creature. not restricted to CBMs. `bionic_group`: an item group that will give an item by +dissecting a creature. not restricted to groups containing CBMs. -`flags` value should be an array of strings. It's the flags that will be added to te items of that entry upon harvesting. +`flags` value should be an array of strings. It's the flags that will be added to te items of that +entry upon harvesting. -`faults` value should be an array of `fault_id` strings. It's the faults that will be added to te items of that entry upon harvesting. +`faults` value should be an array of `fault_id` strings. It's the faults that will be added to te +items of that entry upon harvesting. For every `type` other then `bionic` and `bionic_group` following entries scale the results: - `base_num` value should be an array with two elements in which the first defines the minimum number of the corresponding item produced and the second defines the maximum number. - `scale_num` value should be an array with two elements, increasing the minimum and maximum drop numbers respectively by element value * survival skill. - `max` upper limit after `bas_num` and `scale_num` are calculated using - `mass_ratio` value is a multiplier of how much of the monster's weight comprises the associated item. to conserve mass, keep between 0 and 1 combined with all drops. This overrides `base_num`, `scale_num` and `max` - - -For `type`s: `bionic` and `bionic_group` following enrties can scale the results: - `max` this value (in contrary to `max` for other `type`s) corresponds to maximum butchery roll that will be passed to check_butcher_cbm() in activity_handlers.cpp; view check_butcher_cbm() to see corresponding distribution chances for roll values passed to that function +`base_num` value should be an array with two elements in which the first defines the minimum number +of the corresponding item produced and the second defines the maximum number. `scale_num` value +should be an array with two elements, increasing the minimum and maximum drop numbers respectively +by element value * survival skill. `max` upper limit after `bas_num` and `scale_num` are calculated +using `mass_ratio` value is a multiplier of how much of the monster's weight comprises the +associated item. to conserve mass, keep between 0 and 1 combined with all drops. This overrides +`base_num`, `scale_num` and `max` + +For `type`s: `bionic` and `bionic_group` following enrties can scale the results: `max` this value +(in contrary to `max` for other `type`s) corresponds to maximum butchery roll that will be passed to +check_butcher_cbm() in activity_handlers.cpp; view check_butcher_cbm() to see corresponding +distribution chances for roll values passed to that function ### Weapon Category @@ -2789,7 +2902,8 @@ Used to classify weapons (guns or melee) into groups, mainly for use in martial } ``` -`"name"` is a translatable string used for UI display in martial arts UI, while ID is used for JSON entries. +`"name"` is a translatable string used for UI display in martial arts UI, while ID is used for JSON +entries. ### Furniture @@ -2827,12 +2941,14 @@ Same as for terrain, see below in the chapter "Common to furniture and terrain". #### `move_cost_mod` -Movement cost modifier (`-10` = impassable, `0` = no change). This is added to the movecost of the underlying terrain. +Movement cost modifier (`-10` = impassable, `0` = no change). This is added to the movecost of the +underlying terrain. #### `light_emitted` -How much light the furniture produces. 10 will light the tile it's on brightly, 15 will light that tile and the tiles around it brightly, as well as slightly lighting the tiles two tiles away from the source. -For examples: An overhead light is 120, a utility light, 240, and a console, 10. +How much light the furniture produces. 10 will light the tile it's on brightly, 15 will light that +tile and the tiles around it brightly, as well as slightly lighting the tiles two tiles away from +the source. For examples: An overhead light is 120, a utility light, 240, and a console, 10. #### `required_str` @@ -2840,21 +2956,25 @@ Strength required to move the furniture around. Negative values indicate an unmo #### `crafting_pseudo_item` -(Optional) Id of an item (tool) that will be available for crafting when this furniture is range (the furniture acts as an item of that type). Can be made into an array. -Example: `"crafting_pseudo_item": [ "fake_gridwelder", "fake_gridsolderingiron" ],` +(Optional) Id of an item (tool) that will be available for crafting when this furniture is range +(the furniture acts as an item of that type). Can be made into an array. Example: +`"crafting_pseudo_item": [ "fake_gridwelder", "fake_gridsolderingiron" ],` #### `workbench` -(Optional) Can craft here. Must specify a speed multiplier, allowed mass, and allowed volume. Mass/volume over these limits incur a speed penalty. Must be paired with a `"workbench"` `examine_action` to function. +(Optional) Can craft here. Must specify a speed multiplier, allowed mass, and allowed volume. +Mass/volume over these limits incur a speed penalty. Must be paired with a `"workbench"` +`examine_action` to function. #### `plant_data` -(Optional) This is a plant. Must specify a plant transform, and a base depending on context. You can also add a harvest or growth multiplier if it has the `GROWTH_HARVEST` flag. +(Optional) This is a plant. Must specify a plant transform, and a base depending on context. You can +also add a harvest or growth multiplier if it has the `GROWTH_HARVEST` flag. #### `surgery_skill_multiplier` -(Optional) Surgery skill multiplier (float) applied by this furniture to survivor standing next to it for the purpose of surgery. - +(Optional) Surgery skill multiplier (float) applied by this furniture to survivor standing next to +it for the purpose of surgery. ### Terrain @@ -2894,35 +3014,46 @@ Same as for furniture, see below in the chapter "Common to furniture and terrain #### `move_cost` -Move cost to move through. A value of 0 means it's impassable (e.g. wall). You should not use negative values. The positive value is multiple of 50 move points, e.g. value 2 means the player uses 2\*50 = 100 move points when moving across the terrain. +Move cost to move through. A value of 0 means it's impassable (e.g. wall). You should not use +negative values. The positive value is multiple of 50 move points, e.g. value 2 means the player +uses 2\*50 = 100 move points when moving across the terrain. #### `light_emitted` -How much light the terrain emits. 10 will light the tile it's on brightly, 15 will light that tile and the tiles around it brightly, as well as slightly lighting the tiles two tiles away from the source. -For examples: An overhead light is 120, a utility light, 240, and a console, 10. +How much light the terrain emits. 10 will light the tile it's on brightly, 15 will light that tile +and the tiles around it brightly, as well as slightly lighting the tiles two tiles away from the +source. For examples: An overhead light is 120, a utility light, 240, and a console, 10. #### `trap` (Optional) Id of the build-in trap of that terrain. -For example the terrain `t_pit` has the built-in trap `tr_pit`. Every tile in the game that has the terrain `t_pit` also has, therefore, an implicit trap `tr_pit` on it. The two are inseparable (the player can not deactivate the built-in trap, and changing the terrain will also deactivate the built-in trap). +For example the terrain `t_pit` has the built-in trap `tr_pit`. Every tile in the game that has the +terrain `t_pit` also has, therefore, an implicit trap `tr_pit` on it. The two are inseparable (the +player can not deactivate the built-in trap, and changing the terrain will also deactivate the +built-in trap). A built-in trap prevents adding any other trap explicitly (by the player and through mapgen). #### `harvestable` -(Optional) If defined, the terrain is harvestable. This entry defines the item type of the harvested fruits (or similar). To make this work, you also have to set one of the `harvest_*` `examine_action` functions. +(Optional) If defined, the terrain is harvestable. This entry defines the item type of the harvested +fruits (or similar). To make this work, you also have to set one of the `harvest_*` `examine_action` +functions. #### `transforms_into` -(Optional) Used for various transformation of the terrain. If defined, it must be a valid terrain id. Used for example: +(Optional) Used for various transformation of the terrain. If defined, it must be a valid terrain +id. Used for example: - When harvesting fruits (to change into the harvested form of the terrain). -- In combination with the `HARVESTED` flag and `harvest_season` to change the harvested terrain back into a terrain with fruits. +- In combination with the `HARVESTED` flag and `harvest_season` to change the harvested terrain back + into a terrain with fruits. #### `harvest_season` -(Optional) On of "SUMMER", "AUTUMN", "WINTER", "SPRING", used in combination with the "HARVESTED" flag to revert the terrain back into a terrain that can be harvested. +(Optional) On of "SUMMER", "AUTUMN", "WINTER", "SPRING", used in combination with the "HARVESTED" +flag to revert the terrain back into a terrain that can be harvested. #### `roof` @@ -2934,7 +3065,10 @@ Some values can/must be set for terrain and furniture. They have the same meanin #### `id` -Id of the object, this should be unique among all object of that type (all terrain or all furniture types). By convention (but technically not needed), the id should have the "f_" prefix for furniture and the "t_" prefix for terrain. This is not translated. It must not be changed later as that would break save compatibility. +Id of the object, this should be unique among all object of that type (all terrain or all furniture +types). By convention (but technically not needed), the id should have the "f_" prefix for furniture +and the "t_" prefix for terrain. This is not translated. It must not be changed later as that would +break save compatibility. #### `name` @@ -2946,16 +3080,21 @@ Displayed name of the object. This will be translated. #### `connects_to` -(Optional) The group of terrains to which this terrain connects. This affects tile rotation and connections, and the ASCII symbol drawn by terrain with the flag "AUTO_WALL_SYMBOL". +(Optional) The group of terrains to which this terrain connects. This affects tile rotation and +connections, and the ASCII symbol drawn by terrain with the flag "AUTO_WALL_SYMBOL". Current values: + - `CHAINFENCE` - `RAILING` - `WALL` - `WATER` - `WOODFENCE` -Example: `-` , `|` , `X` and `Y` are terrain which share the same `connects_to` value. `O` does not have it. `X` and `Y` also have the `AUTO_WALL_SYMBOL` flag. `X` will be drawn as a T-intersection (connected to west, south and east), `Y` will be drawn as a horizontal line (going from west to east, no connection to south). +Example: `-` , `|` , `X` and `Y` are terrain which share the same `connects_to` value. `O` does not +have it. `X` and `Y` also have the `AUTO_WALL_SYMBOL` flag. `X` will be drawn as a T-intersection +(connected to west, south and east), `Y` will be drawn as a horizontal line (going from west to +east, no connection to south). ``` -X- -Y- @@ -2964,16 +3103,15 @@ Example: `-` , `|` , `X` and `Y` are terrain which share the same `connects_to` #### `symbol` -ASCII symbol of the object as it appears in the game. The symbol string must be exactly one character long. This can also be an array of 4 strings, which define the symbol during the different seasons. The first entry defines the symbol during spring. If it's not an array, the same symbol is used all year round. +ASCII symbol of the object as it appears in the game. The symbol string must be exactly one +character long. This can also be an array of 4 strings, which define the symbol during the different +seasons. The first entry defines the symbol during spring. If it's not an array, the same symbol is +used all year round. #### `comfort` -How comfortable this terrain/furniture is. Impact ability to fall asleep on it. - uncomfortable = -999, - neutral = 0, - slightly_comfortable = 3, - comfortable = 5, - very_comfortable = 10 +How comfortable this terrain/furniture is. Impact ability to fall asleep on it. uncomfortable = +-999, neutral = 0, slightly_comfortable = 3, comfortable = 5, very_comfortable = 10 #### `floor_bedding_warmth` @@ -2981,21 +3119,28 @@ Bonus warmth offered by this terrain/furniture when used to sleep. #### `bonus_fire_warmth_feet` -Increase warmth received on feet from nearby fire (default = 300) +Increase warmth received on feet from nearby fire (default = 300) #### `looks_like` -id of a similar item that this item looks like. The tileset loader will try to load the tile for that item if this item doesn't have a tile. looks_like entries are implicitly chained, so if 'throne' has looks_like 'big_chair' and 'big_chair' has looks_like 'chair', a throne will be displayed using the chair tile if tiles for throne and big_chair do not exist. If a tileset can't find a tile for any item in the looks_like chain, it will default to the ascii symbol. +id of a similar item that this item looks like. The tileset loader will try to load the tile for +that item if this item doesn't have a tile. looks_like entries are implicitly chained, so if +'throne' has looks_like 'big_chair' and 'big_chair' has looks_like 'chair', a throne will be +displayed using the chair tile if tiles for throne and big_chair do not exist. If a tileset can't +find a tile for any item in the looks_like chain, it will default to the ascii symbol. #### `color` or `bgcolor` -Color of the object as it appears in the game. "color" defines the foreground color (no background color), "bgcolor" defines a solid background color. As with the "symbol" value, this can be an array with 4 entries, each entry being the color during the different seasons. +Color of the object as it appears in the game. "color" defines the foreground color (no background +color), "bgcolor" defines a solid background color. As with the "symbol" value, this can be an array +with 4 entries, each entry being the color during the different seasons. > **NOTE**: You must use ONLY ONE of "color" or "bgcolor" #### `max_volume` -(Optional) Maximal volume that can be used to store items here. Volume in ml and L can be used - "50 ml" or "2 L" +(Optional) Maximal volume that can be used to store items here. Volume in ml and L can be used - "50 +ml" or "2 L" #### `examine_action` @@ -3003,7 +3148,11 @@ Color of the object as it appears in the game. "color" defines the foreground co #### `close" And "open` -(Optional) The value should be a terrain id (inside a terrain entry) or a furniture id (in a furniture entry). If either is defined, the player can open / close the object. Opening / closing will change the object at the affected tile to the given one. For example one could have object "safe_c", which "open"s to "safe_o" and "safe_o" in turn "close"s to "safe_c". Here "safe_c" and "safe_o" are two different terrain (or furniture) types that have different properties. +(Optional) The value should be a terrain id (inside a terrain entry) or a furniture id (in a +furniture entry). If either is defined, the player can open / close the object. Opening / closing +will change the object at the affected tile to the given one. For example one could have object +"safe_c", which "open"s to "safe_o" and "safe_o" in turn "close"s to "safe_c". Here "safe_c" and +"safe_o" are two different terrain (or furniture) types that have different properties. #### `bash` @@ -3011,15 +3160,18 @@ Color of the object as it appears in the game. "color" defines the foreground co #### `deconstruct` -(Optional) Defines whether the object can be deconstructed and if so, what the results shall be. See "map_deconstruct_info". +(Optional) Defines whether the object can be deconstructed and if so, what the results shall be. See +"map_deconstruct_info". #### `pry` -(Optional) Defines whether the object can be pried open and if so, what happens. See "prying_result". +(Optional) Defines whether the object can be pried open and if so, what happens. See +"prying_result". #### `map_bash_info` -Defines the various things that happen when the player or something else bashes terrain or furniture. +Defines the various things that happen when the player or something else bashes terrain or +furniture. ```C++ { @@ -3049,27 +3201,38 @@ Defines the various things that happen when the player or something else bashes TODO #### `sound`, `sound_fail`, `sound_vol`, `sound_fail_vol` -(Optional) Sound and volume of the sound that appears upon destroying the bashed object or upon unsuccessfully bashing it (failing). The sound strings are translated (and displayed to the player). + +(Optional) Sound and volume of the sound that appears upon destroying the bashed object or upon +unsuccessfully bashing it (failing). The sound strings are translated (and displayed to the player). #### `furn_set`, `ter_set` -The terrain / furniture that will be set when the original is destroyed. This is mandatory for bash entries in terrain, but optional for entries in furniture (it defaults to no furniture). +The terrain / furniture that will be set when the original is destroyed. This is mandatory for bash +entries in terrain, but optional for entries in furniture (it defaults to no furniture). #### `explosive` -(Optional) If greater than 0, destroying the object causes an explosion with this strength (see `game::explosion`). + +(Optional) If greater than 0, destroying the object causes an explosion with this strength (see +`game::explosion`). #### `destroy_only` + TODO #### `bash_below` + TODO #### `tent_centers`, `collapse_radius` -(Optional) For furniture that is part of tents, this defines the id of the center part, which will be destroyed as well when other parts of the tent get bashed. The center is searched for in the given "collapse_radius" radius, it should match the size of the tent. + +(Optional) For furniture that is part of tents, this defines the id of the center part, which will +be destroyed as well when other parts of the tent get bashed. The center is searched for in the +given "collapse_radius" radius, it should match the size of the tent. #### `items` -(Optional) An item group (inline) or an id of an item group, see doc/ITEM_SPAWN.md. The default subtype is "collection". Upon successful bashing, items from that group will be spawned. +(Optional) An item group (inline) or an id of an item group, see doc/ITEM_SPAWN.md. The default +subtype is "collection". Upon successful bashing, items from that group will be spawned. #### `map_deconstruct_info` @@ -3083,77 +3246,97 @@ TODO #### `furn_set`, `ter_set` -The terrain / furniture that will be set after the original has been deconstructed. "furn_set" is optional (it defaults to no furniture), "ter_set" is only used upon "deconstruct" entries in terrain and is mandatory there. +The terrain / furniture that will be set after the original has been deconstructed. "furn_set" is +optional (it defaults to no furniture), "ter_set" is only used upon "deconstruct" entries in terrain +and is mandatory there. #### `items` -(Optional) An item group (inline) or an id of an item group, see doc/ITEM_SPAWN.md. The default subtype is "collection". Upon deconstruction the object, items from that group will be spawned. +(Optional) An item group (inline) or an id of an item group, see doc/ITEM_SPAWN.md. The default +subtype is "collection". Upon deconstruction the object, items from that group will be spawned. #### `prying_result` ```JSON { - "success_message": "You pry open the door.", - "fail_message": "You pry, but cannot pry open the door.", - "break_message": "You damage the door!", - "pry_quality": 2, - "pry_bonus_mult": 3, - "noise": 12, - "break_noise": 10, - "sound": "crunch!", - "break_sound": "crack!", - "breakable": true, - "difficulty": 8, - "new_ter_type": "t_door_o", - "new_furn_type": "f_crate_o", - "break_ter_type": "t_door_b", - "break_furn_type": "f_null", - "break_items": [ - { "item": "2x4", "prob": 25 }, - { "item": "wood_panel", "prob": 10 }, - { "item": "splinter", "count": [ 1, 2 ] }, - { "item": "nail", "charges": [ 0, 2 ] } - ] + "success_message": "You pry open the door.", + "fail_message": "You pry, but cannot pry open the door.", + "break_message": "You damage the door!", + "pry_quality": 2, + "pry_bonus_mult": 3, + "noise": 12, + "break_noise": 10, + "sound": "crunch!", + "break_sound": "crack!", + "breakable": true, + "difficulty": 8, + "new_ter_type": "t_door_o", + "new_furn_type": "f_crate_o", + "break_ter_type": "t_door_b", + "break_furn_type": "f_null", + "break_items": [ + { "item": "2x4", "prob": 25 }, + { "item": "wood_panel", "prob": 10 }, + { "item": "splinter", "count": [1, 2] }, + { "item": "nail", "charges": [0, 2] } + ] } ``` #### `new_ter_type`, `new_furn_type` -The terrain / furniture that will be set after the original has been pried open. "furn_set" is optional (it defaults to no furniture), "ter_set" is only used upon "pry" entries in terrain and is mandatory there. +The terrain / furniture that will be set after the original has been pried open. "furn_set" is +optional (it defaults to no furniture), "ter_set" is only used upon "pry" entries in terrain and is +mandatory there. #### `success_message`, `fail_message`, `break_message` -Messages displayed on successfully prying open the terrain / furniture, on failure, or should the terrain / furniture break into something else from a failed pry attempt. `break_message` is only required if `breakable` is set to true and `break_ter_type` is defined. +Messages displayed on successfully prying open the terrain / furniture, on failure, or should the +terrain / furniture break into something else from a failed pry attempt. `break_message` is only +required if `breakable` is set to true and `break_ter_type` is defined. #### `pry_quality`, `pry_bonus_mult`, `difficulty` -This determines the minimum prying quality needed to attempt to pry open the terrain / furniture, and the chance of successfully prying it open. From iuse.cpp: +This determines the minimum prying quality needed to attempt to pry open the terrain / furniture, +and the chance of successfully prying it open. From iuse.cpp: ```C++ - int diff = pry->difficulty; - diff -= ( ( pry_level - pry->pry_quality ) * pry->pry_bonus_mult ); +int diff = pry->difficulty; +diff -= ( ( pry_level - pry->pry_quality ) * pry->pry_bonus_mult ); ``` ```C++ - if( dice( 4, diff ) < dice( 4, p->str_cur ) ) { - p->add_msg_if_player( m_good, pry->success_message ); +if( dice( 4, diff ) < dice( 4, p->str_cur ) ) { + p->add_msg_if_player( m_good, pry->success_message ); ``` -`difficulty` is compared to the character's current strength during the prying attempt. If the available prying quality of your tool is above the required `pry_quality`, effective difficulty is reduced at a rate determined by `pry_bonus_mult`. `pry_bonus_mult` is optional, and defaults to 1 (meaning for every level of prying quality your tool has beyond the minimum, `diff` will be reduced by 1). +`difficulty` is compared to the character's current strength during the prying attempt. If the +available prying quality of your tool is above the required `pry_quality`, effective difficulty is +reduced at a rate determined by `pry_bonus_mult`. `pry_bonus_mult` is optional, and defaults to 1 +(meaning for every level of prying quality your tool has beyond the minimum, `diff` will be reduced +by 1). #### `noise`, `break_noise`, 'sound', 'break_sound' -If `noise` is specified, successfully prying the terrain / furniture open will play `sound` at the specified volume. If `breakable` is true and `break_noise` is specified, breaking the terrain / furniture on a failed prying attempt will play `break_noise` at the specified volume. +If `noise` is specified, successfully prying the terrain / furniture open will play `sound` at the +specified volume. If `breakable` is true and `break_noise` is specified, breaking the terrain / +furniture on a failed prying attempt will play `break_noise` at the specified volume. -If `noise` or `break_noise` are not specified then prying or breaking the terrain / furniture in question will simply be silent and make no sound, making them optional. `sound` and `break_sound` are also optional, with default messages of "crunch!" and "crack!" respectively. +If `noise` or `break_noise` are not specified then prying or breaking the terrain / furniture in +question will simply be silent and make no sound, making them optional. `sound` and `break_sound` +are also optional, with default messages of "crunch!" and "crack!" respectively. #### `breakable`, `break_ter_type`, `break_furn_type` -If `breakable` is set to true, then failed pry attempts have a chance of breaking the terrain / furniture instead. For terrain, `break_ter_type` is mandatory if `breakable` is set to true, `break_furn_type` is optional and defaults to null. +If `breakable` is set to true, then failed pry attempts have a chance of breaking the terrain / +furniture instead. For terrain, `break_ter_type` is mandatory if `breakable` is set to true, +`break_furn_type` is optional and defaults to null. #### `break_items` -(Optional) An item group (inline) or an id of an item group, see doc/ITEM_SPAWN.md. The default subtype is "collection". If `breakable` is set to true, breaking the object from a failed pry attempt will spawn items from that group. +(Optional) An item group (inline) or an id of an item group, see doc/ITEM_SPAWN.md. The default +subtype is "collection". If `breakable` is set to true, breaking the object from a failed pry +attempt will spawn items from that group. ### `plant_data` @@ -3168,19 +3351,23 @@ If `breakable` is set to true, then failed pry attempts have a chance of breakin #### `transform` -What the `PLANT` furniture turn into when it grows a stage, or what a `PLANTABLE` furniture turns into when it is planted on. +What the `PLANT` furniture turn into when it grows a stage, or what a `PLANTABLE` furniture turns +into when it is planted on. #### `base` -What the 'base' furniture of the `PLANT` furniture is - what it would be if there was not a plant growing there. Used when monsters 'eat' the plant to preserve what furniture it is. +What the 'base' furniture of the `PLANT` furniture is - what it would be if there was not a plant +growing there. Used when monsters 'eat' the plant to preserve what furniture it is. #### `growth_multiplier` -A flat multiplier on the growth speed on the plant. For numbers greater than one, it will take longer to grow, and for numbers less than one it will take less time to grow. +A flat multiplier on the growth speed on the plant. For numbers greater than one, it will take +longer to grow, and for numbers less than one it will take less time to grow. #### `harvest_multiplier` -A flat multiplier on the harvest count of the plant. For numbers greater than one, the plant will give more produce from harvest, for numbers less than one it will give less produce from harvest. +A flat multiplier on the harvest count of the plant. For numbers greater than one, the plant will +give more produce from harvest, for numbers less than one it will give less produce from harvest. ### clothing_mod @@ -3221,16 +3408,19 @@ The id member should be the unique id of the scenario. The following properties (mandatory, except if noted otherwise) are supported: - ## `description` + (string) The in-game description. ## `name` + (string or object with members "male" and "female") -The in-game name, either one gender-neutral string, or an object with gender specific names. Example: +The in-game name, either one gender-neutral string, or an object with gender specific names. +Example: + ```C++ "name": { "male": "Runaway groom", @@ -3239,16 +3429,21 @@ The in-game name, either one gender-neutral string, or an object with gender spe ``` ## `points` + (integer) Point cost of scenario. Positive values cost points and negative values grant points. ## `items` + (optional, object with optional members "both", "male" and "female") -Items the player starts with when selecting this scenario. One can specify different items based on the gender of the character. Each lists of items should be an array of items ids. Ids may appear multiple times, in which case the item is created multiple times. +Items the player starts with when selecting this scenario. One can specify different items based on +the gender of the character. Each lists of items should be an array of items ids. Ids may appear +multiple times, in which case the item is created multiple times. Example: + ```C++ "items": { "both": [ @@ -3260,11 +3455,14 @@ Example: "female": [ "panties" ] } ``` + This gives the player pants, two rocks and (depending on the gender) briefs or panties. -Mods can modify the lists of an existing scenario via "add:both" / "add:male" / "add:female" and "remove:both" / "remove:male" / "remove:female". +Mods can modify the lists of an existing scenario via "add:both" / "add:male" / "add:female" and +"remove:both" / "remove:male" / "remove:female". Example for mods: + ```C++ { "type": "scenario", @@ -3278,6 +3476,7 @@ Example for mods: ``` ## `flags` + (optional, array of strings) A list of flags. TODO: document those flags here. @@ -3285,6 +3484,7 @@ A list of flags. TODO: document those flags here. Mods can modify this via "add:flags" and "remove:flags". ## `cbms` + (optional, array of strings) A list of CBM ids that are implanted in the character. @@ -3292,40 +3492,57 @@ A list of CBM ids that are implanted in the character. Mods can modify this via "add:CBMs" and "remove:CBMs". ## `traits", "forced_traits", "forbidden_traits` + (optional, array of strings) -Lists of trait/mutation ids. Traits in "forbidden_traits" are forbidden and can't be selected during the character creation. Traits in "forced_traits" are automatically added to character. Traits in "traits" enables them to be chosen, even if they are not starting traits. +Lists of trait/mutation ids. Traits in "forbidden_traits" are forbidden and can't be selected during +the character creation. Traits in "forced_traits" are automatically added to character. Traits in +"traits" enables them to be chosen, even if they are not starting traits. -Mods can modify this via "add:traits" / "add:forced_traits" / "add:forbidden_traits" and "remove:traits" / "remove:forced_traits" / "remove:forbidden_traits". +Mods can modify this via "add:traits" / "add:forced_traits" / "add:forbidden_traits" and +"remove:traits" / "remove:forced_traits" / "remove:forbidden_traits". ## `allowed_locs` + (optional, array of strings) -A list of starting location ids (see start_locations.json) that can be chosen when using this scenario. +A list of starting location ids (see start_locations.json) that can be chosen when using this +scenario. ## `start_name` + (string) -The name that is shown for the starting location. This is useful if the scenario allows several starting locations, but the game can not list them all at once in the scenario description. Example: if the scenario allows to start somewhere in the wilderness, the starting locations would contain forest and fields, but its "start_name" may simply be "wilderness". +The name that is shown for the starting location. This is useful if the scenario allows several +starting locations, but the game can not list them all at once in the scenario description. Example: +if the scenario allows to start somewhere in the wilderness, the starting locations would contain +forest and fields, but its "start_name" may simply be "wilderness". ## `professions` + (optional, array of strings) -A list of allowed professions that can be chosen when using this scenario. The first entry is the default profession. If this is empty, all professions are allowed. +A list of allowed professions that can be chosen when using this scenario. The first entry is the +default profession. If this is empty, all professions are allowed. ## `map_special` + (optional, string) Add a map special to the starting location, see JSON_FLAGS for the possible specials. ## `missions` + (optional, array of strings) -A list of mission ids that will be started and assigned to the player at the start of the game. Only missions with the ORIGIN_GAME_START origin are allowed. The last mission in the list will be the active mission, if multiple missions are assigned. +A list of mission ids that will be started and assigned to the player at the start of the game. Only +missions with the ORIGIN_GAME_START origin are allowed. The last mission in the list will be the +active mission, if multiple missions are assigned. # Starting locations Starting locations are specified as JSON object with "type" member set to "start_location": + ```C++ { "type": "start_location", @@ -3341,138 +3558,148 @@ The id member should be the unique id of the location. The following properties (mandatory, except if noted otherwise) are supported: ## `name` + (string) The in-game name of the location. ## `target` + (string) -The id of an overmap terrain type (see overmap_terrain.json) of the starting location. The game will chose a random place with that terrain. +The id of an overmap terrain type (see overmap_terrain.json) of the starting location. The game will +chose a random place with that terrain. ## `flags` + (optional, array of strings) Arbitrary flags. Mods can modify this via "add:flags" / "remove:flags". TODO: document them. ### `tile_config` -Each tileset has a tile_config.json describing how to map the contents of a sprite sheet to various tile identifiers, different orientations, etc. The ordering of the overlays used for displaying mutations can be controlled as well. The ordering can be used to override the default ordering provided in `mutation_ordering.json`. Example: + +Each tileset has a tile_config.json describing how to map the contents of a sprite sheet to various +tile identifiers, different orientations, etc. The ordering of the overlays used for displaying +mutations can be controlled as well. The ordering can be used to override the default ordering +provided in `mutation_ordering.json`. Example: ```C++ - { // whole file is a single object - "tile_info": [ // tile_info is mandatory - { - "height": 32, - "width": 32, - "iso" : true, // Optional. Indicates an isometric tileset. Defaults to false. - "pixelscale" : 2 // Optional. Sets a multiplier for resizing a tileset. Defaults to 1. - } - ], - "tiles-new": [ // tiles-new is an array of sprite sheets - { // alternately, just one "tiles" array - "file": "tiles.png", // file containing sprites in a grid - "tiles": [ // array with one entry per tile - { - "id": "10mm", // id is how the game maps things to sprites - "fg": 1, // lack of prefix mostly indicates items - "bg": 632, // fg and bg can be sprite indexes in the image - "rotates": false - }, - { - "id": "t_wall", // "t_" indicates terrain - "fg": [2918, 2919, 2918, 2919], // 2 or 4 sprite numbers indicates pre-rotated - "bg": 633, - "rotates": true, - "multitile": true, - "additional_tiles": [ // connected/combined versions of sprite - { // or variations, see below - "id": "center", - "fg": [2919, 2918, 2919, 2918] - }, - { - "id": "corner", - "fg": [2924, 2922, 2922, 2923] - }, - { - "id": "end_piece", - "fg": [2918, 2919, 2918, 2919] - }, - { - "id": "t_connection", - "fg": [2919, 2918, 2919, 2918] - }, - { - "id": "unconnected", - "fg": 2235 - } - ] - }, - { - "id": "vp_atomic_lamp", // "vp_" vehicle part - "fg": 3019, - "bg": 632, - "rotates": false, - "multitile": true, - "additional_tiles": [ - { - "id": "broken", // variant sprite - "fg": 3021 - } - ] - }, - { - "id": "t_dirt", - "rotates": false, - "fg": [ - { "weight":50, "sprite":640}, // weighted random variants - { "weight":1, "sprite":3620}, - { "weight":1, "sprite":3621}, - { "weight":1, "sprite":3622} - ] - }, - { - "id": [ - "overlay_mutation_GOURMAND", // character overlay for mutation - "overlay_mutation_male_GOURMAND", // overlay for specified gender - "overlay_mutation_active_GOURMAND" // overlay for activated mutation - ], - "fg": 4040 - } - ] - }, - { // second entry in tiles-new - "file": "moretiles.png", // another sprite sheet - "tiles": [ - { - "id": ["xxx","yyy"], // define two ids at once - "fg": 1, - "bg": 234 - } - ] - } - ], - "overlay_ordering": [ - { - "id" : "WINGS_BAT", // mutation name, in a string or array of strings - "order" : 1000 // range from 0 - 9999, 9999 being the topmost layer - }, - { - "id" : [ "PLANTSKIN", "BARK" ], // mutation name, in a string or array of strings - "order" : 3500 // order is applied to all items in the array - }, - { - "id" : "bio_armor_torso", // Overlay order of bionics is controlled in the same way - "order" : 500 - } - ] - } +{ // whole file is a single object + "tile_info": [ // tile_info is mandatory + { + "height": 32, + "width": 32, + "iso" : true, // Optional. Indicates an isometric tileset. Defaults to false. + "pixelscale" : 2 // Optional. Sets a multiplier for resizing a tileset. Defaults to 1. + } + ], + "tiles-new": [ // tiles-new is an array of sprite sheets + { // alternately, just one "tiles" array + "file": "tiles.png", // file containing sprites in a grid + "tiles": [ // array with one entry per tile + { + "id": "10mm", // id is how the game maps things to sprites + "fg": 1, // lack of prefix mostly indicates items + "bg": 632, // fg and bg can be sprite indexes in the image + "rotates": false + }, + { + "id": "t_wall", // "t_" indicates terrain + "fg": [2918, 2919, 2918, 2919], // 2 or 4 sprite numbers indicates pre-rotated + "bg": 633, + "rotates": true, + "multitile": true, + "additional_tiles": [ // connected/combined versions of sprite + { // or variations, see below + "id": "center", + "fg": [2919, 2918, 2919, 2918] + }, + { + "id": "corner", + "fg": [2924, 2922, 2922, 2923] + }, + { + "id": "end_piece", + "fg": [2918, 2919, 2918, 2919] + }, + { + "id": "t_connection", + "fg": [2919, 2918, 2919, 2918] + }, + { + "id": "unconnected", + "fg": 2235 + } + ] + }, + { + "id": "vp_atomic_lamp", // "vp_" vehicle part + "fg": 3019, + "bg": 632, + "rotates": false, + "multitile": true, + "additional_tiles": [ + { + "id": "broken", // variant sprite + "fg": 3021 + } + ] + }, + { + "id": "t_dirt", + "rotates": false, + "fg": [ + { "weight":50, "sprite":640}, // weighted random variants + { "weight":1, "sprite":3620}, + { "weight":1, "sprite":3621}, + { "weight":1, "sprite":3622} + ] + }, + { + "id": [ + "overlay_mutation_GOURMAND", // character overlay for mutation + "overlay_mutation_male_GOURMAND", // overlay for specified gender + "overlay_mutation_active_GOURMAND" // overlay for activated mutation + ], + "fg": 4040 + } + ] + }, + { // second entry in tiles-new + "file": "moretiles.png", // another sprite sheet + "tiles": [ + { + "id": ["xxx","yyy"], // define two ids at once + "fg": 1, + "bg": 234 + } + ] + } + ], + "overlay_ordering": [ + { + "id" : "WINGS_BAT", // mutation name, in a string or array of strings + "order" : 1000 // range from 0 - 9999, 9999 being the topmost layer + }, + { + "id" : [ "PLANTSKIN", "BARK" ], // mutation name, in a string or array of strings + "order" : 3500 // order is applied to all items in the array + }, + { + "id" : "bio_armor_torso", // Overlay order of bionics is controlled in the same way + "order" : 500 + } + ] +} ``` # Mutation overlay ordering -The file `mutation_ordering.json` defines the order that visual mutation and bionic overlays are rendered on a character ingame. The layering value from 0 (bottom) - 9999 (top) sets the order. +The file `mutation_ordering.json` defines the order that visual mutation and bionic overlays are +rendered on a character ingame. The layering value from 0 (bottom) - 9999 (top) sets the order. Example: + ```C++ [ { @@ -3501,26 +3728,32 @@ Example: ``` ## `id` + (string) -The internal ID of the mutation. Can be provided as a single string, or an array of strings. The order value provided will be applied to all items in the array. +The internal ID of the mutation. Can be provided as a single string, or an array of strings. The +order value provided will be applied to all items in the array. ## `order` + (integer) -The ordering value of the mutation overlay. Values range from 0 - 9999, 9999 being the topmost drawn layer. Mutations that are not in any list will default to 9999. +The ordering value of the mutation overlay. Values range from 0 - 9999, 9999 being the topmost drawn +layer. Mutations that are not in any list will default to 9999. # MOD_INFO Also see [MODDING.md](MODDING.md). -Object with `MOD_INFO` type describes the mod itself. -Each mod must have exactly one `MOD_INFO`, and unlike other types of objects from mods it is loaded on game launch, -before the title screen shows up. As such, any and all errors related to it will show up before the title screen shows up. +Object with `MOD_INFO` type describes the mod itself. Each mod must have exactly one `MOD_INFO`, and +unlike other types of objects from mods it is loaded on game launch, before the title screen shows +up. As such, any and all errors related to it will show up before the title screen shows up. -Current convention is to put your `MOD_INFO` in `mod_info.json` file within the root directory of the mod. +Current convention is to put your `MOD_INFO` in `mod_info.json` file within the root directory of +the mod. Example: + ```C++ [ { @@ -3559,9 +3792,11 @@ Example: # MOD tileset -MOD tileset defines additional sprite sheets. It is specified as JSON object with `type` member set to `mod_tileset`. +MOD tileset defines additional sprite sheets. It is specified as JSON object with `type` member set +to `mod_tileset`. Example: + ```C++ [ { @@ -3589,39 +3824,28 @@ Example: ``` ## `compatibility` + (string) -The internal ID of the compatible tilesets. MOD tileset is only applied when base tileset's ID exists in this field. +The internal ID of the compatible tilesets. MOD tileset is only applied when base tileset's ID +exists in this field. ## `tiles-new` -Setting of sprite sheets. Same as `tiles-new` field in `tile_config`. Sprite files are loaded from the same folder json file exists. +Setting of sprite sheets. Same as `tiles-new` field in `tile_config`. Sprite files are loaded from +the same folder json file exists. # Field types - { - "type": "field_type", // this is a field type - "id": "fd_gum_web", // id of the field - "immune_mtypes": [ "mon_spider_gum" ], // list of monster immune to this field - "intensity_levels": [ - { "name": "shadow", // name of this level of intensity - "light_override": 3.7 } //light level on the tile occupied by this field will be set at 3.7 not matter the ambient light. - ], - "bash": { - "str_min": 1, // lower bracket of bashing damage required to bash - "str_max": 3, // higher bracket - "sound_vol": 2, // noise made when succesfully bashing the field - "sound_fail_vol": 2, // noise made when failing to bash the field - "sound": "shwip", // sound on success - "sound_fail": "shwomp", // sound on failure - "msg_success": "You brush the gum web aside.", // message on success - "move_cost": 120, // how many moves it costs to succesfully bash that field (default: 100) - "items": [ // item dropped upon succesful bashing - { "item": "2x4", "count": [ 5, 8 ] }, - { "item": "nail", "charges": [ 6, 8 ] }, - { "item": "splinter", "count": [ 3, 6 ] }, - { "item": "rag", "count": [ 40, 55 ] }, - { "item": "scrap", "count": [ 10, 20 ] } - ] - } - } +{ "type": "field_type", // this is a field type "id": "fd_gum_web", // id of the field +"immune_mtypes": [ "mon_spider_gum" ], // list of monster immune to this field "intensity_levels": [ +{ "name": "shadow", // name of this level of intensity "light_override": 3.7 } //light level on the +tile occupied by this field will be set at 3.7 not matter the ambient light. ], "bash": { "str_min": +1, // lower bracket of bashing damage required to bash "str_max": 3, // higher bracket "sound_vol": +2, // noise made when succesfully bashing the field "sound_fail_vol": 2, // noise made when failing +to bash the field "sound": "shwip", // sound on success "sound_fail": "shwomp", // sound on failure +"msg_success": "You brush the gum web aside.", // message on success "move_cost": 120, // how many +moves it costs to succesfully bash that field (default: 100) "items": [ // item dropped upon +succesful bashing { "item": "2x4", "count": [ 5, 8 ] }, { "item": "nail", "charges": [ 6, 8 ] }, { +"item": "splinter", "count": [ 3, 6 ] }, { "item": "rag", "count": [ 40, 55 ] }, { "item": "scrap", +"count": [ 10, 20 ] } ] } } diff --git a/doc/JSON_INHERITANCE.md b/doc/JSON_INHERITANCE.md index ee53b72e8d6b..4cc6919492a7 100644 --- a/doc/JSON_INHERITANCE.md +++ b/doc/JSON_INHERITANCE.md @@ -1,8 +1,12 @@ # JSON Inheritance -To reduce duplication in the JSON data it is possible for some types to inherit from an existing type. + +To reduce duplication in the JSON data it is possible for some types to inherit from an existing +type. ## Examples -In the following condensed example ```556``` ammo is derived from ```223``` ammo via ```copy-from```: + +In the following condensed example `556` ammo is derived from `223` ammo via `copy-from`: + ``` "id": "556", "copy-from": "223", @@ -16,19 +20,26 @@ In the following condensed example ```556``` ammo is derived from ```223``` ammo }, "extend": { "effects": [ "NEVER_MISFIRES" ] } ``` + The following rules apply to the above example: -* Missing fields have the same value as the parent +- Missing fields have the same value as the parent -* Fields explicitly specified replace those of the parent type. The above example replaces ```name```, ```description``` and ```price```. +- Fields explicitly specified replace those of the parent type. The above example replaces `name`, + `description` and `price`. -* Numeric values may be specified ```relative``` to the parent. For example ```556``` has less ```damage``` but more ```pierce``` than ```223``` and will maintain this relationship if the definition for ```223``` is changed. +- Numeric values may be specified `relative` to the parent. For example `556` has less `damage` but + more `pierce` than `223` and will maintain this relationship if the definition for `223` is + changed. -* Flags can be added via ```extend```. For example ```556``` is military ammo and gains the ```NEVER_MISFIRES``` ammo effect. Any existing flags specified from ```223``` are preserved. +- Flags can be added via `extend`. For example `556` is military ammo and gains the `NEVER_MISFIRES` + ammo effect. Any existing flags specified from `223` are preserved. -* The entry you copied from must be of the same ```type``` as the item you added or changed (not all types are supported, see 'support' below) +- The entry you copied from must be of the same `type` as the item you added or changed (not all + types are supported, see 'support' below) -Reloaded ammo is derived from the factory equivalent but with a 10% penalty to ```damage``` and ```dispersion``` and a chance to misfire: +Reloaded ammo is derived from the factory equivalent but with a 10% penalty to `damage` and +`dispersion` and a chance to misfire: ``` "id": "reloaded_556", @@ -42,15 +53,22 @@ Reloaded ammo is derived from the factory equivalent but with a 10% penalty to ` "extend": { "effects": [ "RECYCLED" ] }, "delete": { "effects": [ "NEVER_MISFIRES" ] } ``` + The following additional rules apply to the above example: -Chained inheritance is possible; for example ```reloaded_556``` inherits from ```556``` which is itself derived from ```223``` +Chained inheritance is possible; for example `reloaded_556` inherits from `556` which is itself +derived from `223` -Numeric values may be specified ```proportional``` to the parent by via a decimal factor where ```0.5``` is 50% and ```2.0``` is 200%. +Numeric values may be specified `proportional` to the parent by via a decimal factor where `0.5` is +50% and `2.0` is 200%. -Flags can be deleted via ```delete```. It is not an error if the deleted flag does not exist in the parent. +Flags can be deleted via `delete`. It is not an error if the deleted flag does not exist in the +parent. + +It is possible to define an `abstract` type that exists only for other types to inherit from and +cannot itself be used in game. In the following condensed example `magazine_belt` provides values +common to all implemented ammo belts: -It is possible to define an ```abstract``` type that exists only for other types to inherit from and cannot itself be used in game. In the following condensed example ```magazine_belt``` provides values common to all implemented ammo belts: ``` "abstract": "magazine_belt", "type": "MAGAZINE", @@ -63,14 +81,18 @@ It is possible to define an ```abstract``` type that exists only for other types }, "flags": [ "MAG_BELT", "MAG_DESTROY" ] ``` + The following additional rules apply to the above example: -Missing mandatory fields do not result in errors as the ```abstract``` type is discarded after JSON loading completes +Missing mandatory fields do not result in errors as the `abstract` type is discarded after JSON +loading completes Missing optional fields are set to the usual defaults for that type ## Support + The following types currently support inheritance: + ``` GENERIC AMMO @@ -83,12 +105,21 @@ BOOK ENGINE ``` -To find out if a types supports copy-from, you need to know if it has implemented generic_factory. To find out if this is the case, do the following: -* Open [init.cpp](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/src/init.cpp) -* Find the line that mentions your type, for example `add( "gate", &gates::load );` -* Copy the load function, in this case it would be *gates::load* -* Use this in [the search bar on github](https://github.com/CleverRaven/Cataclysm-DDA/search?q=%22gates%3A%3Aload%22&unscoped_q=%22gates%3A%3Aload%22&type=Code) to find the file that contains *gates::load* -* In the search results you find [gates.cpp](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/src/gates.cpp). open it. -* In gates.cpp, find the generic_factory line, it looks like this: `generic_factory gates_data( "gate type", "handle", "other_handles" );` -* Since the generic_factory line is present, you can now conclude that it supports copy-from. -* If you don't find generic_factoy present, it does not support copy-from, as is the case for type vitamin (repeat the above steps and find that [vitamin.cpp](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/src/vitamin.cpp) does not contain generic_factoy) +To find out if a types supports copy-from, you need to know if it has implemented generic_factory. +To find out if this is the case, do the following: + +- Open [init.cpp](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/src/init.cpp) +- Find the line that mentions your type, for example `add( "gate", &gates::load );` +- Copy the load function, in this case it would be _gates::load_ +- Use this in + [the search bar on github](https://github.com/CleverRaven/Cataclysm-DDA/search?q=%22gates%3A%3Aload%22&unscoped_q=%22gates%3A%3Aload%22&type=Code) + to find the file that contains _gates::load_ +- In the search results you find + [gates.cpp](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/src/gates.cpp). open it. +- In gates.cpp, find the generic_factory line, it looks like this: + `generic_factory gates_data( "gate type", "handle", "other_handles" );` +- Since the generic_factory line is present, you can now conclude that it supports copy-from. +- If you don't find generic_factoy present, it does not support copy-from, as is the case for type + vitamin (repeat the above steps and find that + [vitamin.cpp](https://github.com/CleverRaven/Cataclysm-DDA/tree/master/src/vitamin.cpp) does not + contain generic_factoy) diff --git a/doc/JSON_STYLE.md b/doc/JSON_STYLE.md index 9cd950bb341f..3799f6668823 100644 --- a/doc/JSON_STYLE.md +++ b/doc/JSON_STYLE.md @@ -1,8 +1,10 @@ # JSON Style Guide -Like in `doc/CODE_STYLE.md`, the JSON styling policy is to update JSON as it is added or edited, and in relatively small chunks otherwise in order to prevent undue disruption to development. +Like in `doc/CODE_STYLE.md`, the JSON styling policy is to update JSON as it is added or edited, and +in relatively small chunks otherwise in order to prevent undue disruption to development. -We haven't been able to find a decent JSON styling tool, so we wrote our own. It lives in tools/format/format.cpp and it leverages src/json.cpp to parse and emit JSON. +We haven't been able to find a decent JSON styling tool, so we wrote our own. It lives in +tools/format/format.cpp and it leverages src/json.cpp to parse and emit JSON. ## JSON Example @@ -13,7 +15,7 @@ This example outlines most of the styling features: { "type": "foo", "id": "example", - "short_array": [ 1, 2, 3, 4, 5 ], + "short_array": [1, 2, 3, 4, 5], "short_object": { "item_a": "a", "item_b": "b" @@ -24,46 +26,45 @@ This example outlines most of the styling features: ], "nested_array": [ [ - [ "item1", "value1" ], - [ "item2", "value2" ], - [ "item3", "value3" ], - [ "item4", "value4" ], - [ "item5", "value5" ], - [ "item6", "value6" ] + ["item1", "value1"], + ["item2", "value2"], + ["item3", "value3"], + ["item4", "value4"], + ["item5", "value5"], + ["item6", "value6"] ] ] } ] ``` -Indention is two spaces. -All JSON delimiters except comma and colon are surrounded by whitespace (either a space or a newline). -Comma and colon are followed by whitespace. -Object entries are always newline-separated. -Array entries are newline-separated if the resulting array would exceed 120 characters otherwise (including indention). -Line breaks occur after open brackets, close brackets, or entries. + +Indention is two spaces. All JSON delimiters except comma and colon are surrounded by whitespace +(either a space or a newline). Comma and colon are followed by whitespace. Object entries are always +newline-separated. Array entries are newline-separated if the resulting array would exceed 120 +characters otherwise (including indention). Line breaks occur after open brackets, close brackets, +or entries. ## Formatting tool -The formatting tool can be invoked via the Makefile, directly as `tools/format/json_formatter.cgi` (built via `make style-json`), or via cgi at http://dev.narc.ro/cataclysm/format.html +The formatting tool can be invoked via the Makefile, directly as `tools/format/json_formatter.cgi` +(built via `make style-json`), or via cgi at http://dev.narc.ro/cataclysm/format.html -If you're using the Visual Studio solution, you can configure Visual Studio with -commands to format all of the JSON in the project. +If you're using the Visual Studio solution, you can configure Visual Studio with commands to format +all of the JSON in the project. -1. Build the JsonFormatter project by either building the entire solution or - just that project. This will create a `tools/format/json_formatter.exe` - binary. -2. Add a new external tool entry ( `Tools` > `External Tools..` > `Add` ) and - configure it as follows: - * Title: `Lint All JSON` - * Command: `C:\windows\system32\windowspowershell\v1.0\powershell.exe` - * Arguments: `-file $(SolutionDir)\style-json.ps1` - * Initial Directory: `$(SolutionDir)` - * Use Output window: *checked* +1. Build the JsonFormatter project by either building the entire solution or just that project. This + will create a `tools/format/json_formatter.exe` binary. +2. Add a new external tool entry ( `Tools` > `External Tools..` > `Add` ) and configure it as + follows: + - Title: `Lint All JSON` + - Command: `C:\windows\system32\windowspowershell\v1.0\powershell.exe` + - Arguments: `-file $(SolutionDir)\style-json.ps1` + - Initial Directory: `$(SolutionDir)` + - Use Output window: _checked_ -At this point, you can use the menu ( `Tools` > `Lint All JSON` ) to invoke the -command and can look in the Output Window for the output of running it. -Additionally, you can configure a keybinding for this command by navigating to -`Tools` > `Options` > `Environment` > `Keyboard`, searching for commands -containing `Tools.ExternalCommand` and pick the one that corresponds to the -position of your command in the list (e.g. `Tools.ExternalCommand1` if it's the -top item in the list) and then assign shortcut keys to it. +At this point, you can use the menu ( `Tools` > `Lint All JSON` ) to invoke the command and can look +in the Output Window for the output of running it. Additionally, you can configure a keybinding for +this command by navigating to `Tools` > `Options` > `Environment` > `Keyboard`, searching for +commands containing `Tools.ExternalCommand` and pick the one that corresponds to the position of +your command in the list (e.g. `Tools.ExternalCommand1` if it's the top item in the list) and then +assign shortcut keys to it. diff --git a/doc/LUA_SUPPORT.md b/doc/LUA_SUPPORT.md new file mode 100644 index 000000000000..4134a306b723 --- /dev/null +++ b/doc/LUA_SUPPORT.md @@ -0,0 +1,533 @@ +# LUA SUPPORT + +Use the `Home` key to return to the top. + +- [LUA SUPPORT](#lua-support) + - [Introduction](#introduction) + - [Useful links](#useful-links) + - [Example mods](#example-mods) + - [Ingame Lua console](#ingame-lua-console) + - [Lua hot-reload](#lua-hot-reload) + - [Game data loading](#game-data-loading) + - [preload.lua](#preloadlua) + - [finalize.lua](#finalizelua) + - [main.lua](#mainlua) + - [Lua API details](#lua-api-details) + - [Lua libraries and functions](#lua-libraries-and-functions) + - [Global state](#global-state) + - [Game Bindings](#game-bindings) + - [Global overrides](#global-overrides) + - [Hooks](#hooks) + - [Item use function](#item-use-function) + - [Translation functions](#translation-functions) + - [C++ layout](#c-layout) + - [Lua source files](#lua-source-files) + - [Sol2 source files](#sol2-source-files) + - [Game source files](#game-source-files) + - [Adding new type to the doc generator without binding internals](#adding-new-type-to-the-doc-generator-without-binding-internals) + - [Binding new type to Lua](#binding-new-type-to-lua) + - [Binding new enum to Lua](#binding-new-enum-to-lua) + - [Binding new string\_id or int\_id to Lua](#binding-new-string_id-or-int_id-to-lua) + +## Introduction + +This document describes implementation details behind Lua integration in Cataclysm: Bright Nights. + +BN uses Lua 5.3.6 to run scripts and relies on sol2 v3.3.0 for bindings on C++ side. + +## Useful links + +Lua 5.3 Reference Manual: https://www.lua.org/manual/5.3/ + +Sol2 documentation: https://sol2.readthedocs.io/en/latest/ + +Programming in Lua (first edition): https://www.lua.org/pil/contents.html + +## Example mods + +There are a couple heavily-commented example mods in `data/mods/` that make use of Lua API described +here: + +- `smart_house_remotes` - Add remotes for controlling garage doors and window curtains. +- `saveload_lua_test` - Mod for testing Lua save/load API. + +## Ingame Lua console + +In-game Lua console is available through the debug menu or via `Lua Console` hotkey (unbound by +default). + +It is rather simple, but is capable of keeping input history, showing output and errors from Lua +scripts as well as running Lua snippets and printing the returned values. + +You can adjust console log capacity by running `gdebug.set_log_capacity( num )` (default is 100 +entries), or clear it by running `gdebug.clear_lua_log()`. + +## Lua hot-reload + +To speed up mod development process, BN supports Lua hot-reload functionality. + +There is no filesystem watcher, so hot-reload must be triggered manually via a corresponding +`Reload Lua Code` hotkey (unbound by default). The hot-reload can also be triggered from console +window by pressing the corresponding hotkey, or by running `gdebug.reload_lua_code()` command. +Running the command from regular Lua scripts may have unintended consequences, use at your own risk! + +Note that not all code can be hot-reloaded, it'll be explained in later sections. + +## Game data loading + +When a world is being loaded, game does it in roughly these steps: + +1. Initializes world-related internal state, sets the world as active +2. Loads world's artifact item types (artifacts are hacky and will likely be removed soon in favor + of relics + Lua) +3. Retrieves list of mods used by the world +4. Loads the mods according to the list +5. Initializes avatar-related internal state +6. Loads from save dir actual overmap data, avatar data and reality bubble data + +What we care about here is the mod loading stage. It has a number of sub-steps: + +1. Loading function receives list of world mods +2. It discards the missing ones and prints debug message for each +3. It checks remaining mods on the list, and throws error if a mod needs Lua, but the game build + does NOT support Lua +4. It also throws a warning if game's Lua API version differs from the one used by the mod +5. For every mod on the list that uses Lua, it runs the mod's `preload.lua` script (if present) +6. It goes over all mods in same order as in the list, and loads JSON definitions from each mod's + folder +7. It finalizes loaded data (resolves copy-from, prepares some types with complex state for use) +8. For every mod on the list that uses Lua, it runs the mod's `finalize.lua` script (if present) +9. It checks consistency of loaded data (validates values, warns about iffy combinations of values, + etc.) +10. (R) For every mod on the list that uses Lua, it runs the mod's `main.lua` script (if present) + +As such, we only have 3 scipts to place a mod's Lua code into: `preload.lua`, `finalize.lua` and +`main.lua`. The differences between the 3 and their intended use cases will be explained below. + +You can use only one script, two or all three, depending on your needs. + +When executing hot-reload, the game repeats the step marked with (R). That means if you want the +code you're working on to be hot-reloadable, put it into `main.lua`. + +### preload.lua + +This script is supposed to register event hooks and set up definitions that will then be referred by +game JSON loading system (e.g. item use actions). Note that you can registers them here, and define +them in some later stage (e.g. in `main.lua` to allow hot-reload to affect your hooks). + +### finalize.lua + +This script is supposed to allow mods to modify definitions loaded from JSON after copy-from has +been resolved, but there is no API for this yet. + +TODO: api for finalization + +### main.lua + +This script is supposed to implement the main logic of the mod. This includes, but not limited, to: + +1. Mod runtime state +2. Mod initialization on game start +3. Mod save/load code, if required +4. Implementation of hooks that were set up in `preload.lua` + +## Lua API details + +While you can do a lot of interesting stuff with vanilla Lua, the integration imposes some limits to +prevent potential bugs: + +- Loading packages (or Lua modules) is disabled. +- Your current mod id is stored in `game.current_mod` variable +- Your mod's runtime state should live in `game.mod_runtime[ game.current_mod ]` table. You can also + interface with other mods if you know their id, by accessing their runtime state in a similar way + with `game.mod_runtime[ that_other_mod_id ]` +- Changes to global state are not available between scripts. This is to prevent accidental + collisions between function names and variable names. You still can define global variables and + functions, but they will be visible to your mod only. + +### Lua libraries and functions + +When script is called, it comes with some standard Lua libraries pre-loaded: + +| Library | Description | +| -------- | -------------------------------------------- | +| `base` | print, assert, and other base functions | +| `math` | all things math | +| `string` | string library | +| `table` | the table manipulator and observer functions | + +See `Standard Libraries` section in Lua manual for details. + +Some of the functions here are overloaded by BN, see [Global overrides](#global-overrides) for +details. + +### Global state + +Most of necessary data and game runtime state is available through global `game` table. It has the +following members: + +game.current_mod Id of mod that's being loaded (available only when script is executed) +game.active_mods List of active world mods, in load order game.mod_runtime. Runtime data for +mods (each mod gets its own table named after its id) game.mod_storage. Per-mod storage that +gets automatically saved/loaded on game save/load. game.cata_internal For internal game purposes, +please don't use this game.hooks. Hooks exposed to Lua scripts, will be called on +corresponding events game.iuse. Item use functions that will be recognized by the item +factory and called on item use + +### Game Bindings + +The game exposes various functions, constants and types to Lua. Functions and constants are +organized into "libraries" for organizational purposes. Types are available globally, and may have +member functions and fields. + +To see the full list of functions, constants and types, run the game with `--lua-doc` command line +argument. This will generate documentation file `lua_doc.md` that will be placed in your `config` +folder. + +#### Global overrides + +Some functions have been globally overriden to improve integration with the game. + +| Function | Description | +| ---------- | -------------------------------------------------------------- | +| print | Print as `INFO LUA` to debug.log (overrides default Lua print) | +| dofile | Disabled | +| loadfile | Disabled | +| load | Disabled | +| loadstring | Disabled | + +TODO: alternatives for dofile and such + +#### Hooks + +To see the list of hooks, check `hooks_doc` section of the autogenerated documentation file. There, +you will see the list of hook ids as well as function signatures that they expect. You can register +new hooks by appending to the hooks table like so: + +```lua +-- In preload.lua +local mod = game.mod_runtime[ game.current_mod ] +game.hooks.on_game_save[ #game.hooks.on_game_save + 1 ] = function( ... ) + -- This is essentially a forward declaration. + -- We declare that the hook exists, it should be called on game_save event, + -- but we will forward all possible arguments (even if there is none) to, + -- and return value from, the function that we'll declare later on. + return mod.my_awesome_hook( ... ) +end + +-- In main.lua +local mod = game.mod_runtime[ game.current_mod ] +mod.my_awesome_hook = function() + -- Do actual work here +end +``` + +#### Item use function + +Item use functions use unique id to register themselves in item factory. On item activation, they +receive multiple arguments that will be described in the example below. + +```lua +-- In preload.lua +local mod = game.mod_runtime[ game.current_mod ] +game.iuse_functions[ "SMART_HOUSE_REMOTE" ] = function(...) + -- This is just a forward declaration, + -- but it will allow us to use SMART_HOUSE_REMOTE iuse in JSONs. + return mod.my_awesome_iuse_function(...) +end + +-- In main.lua +local mod = game.mod_runtime[ game.current_mod ] +mod.my_awesome_iuse_function = function( who, item, pos ) + -- Do actual activation effect here. + -- `who` is the character that activated the item + -- `item` is the item itself + -- `pos` is the position of the item (equal to character pos if character has it on them) +end +``` + +#### Translation functions + +To make the mod translatable to other languages, get your text via functions bound in `locale` +library. See [TRANSLATING.md](TRANSLATING.md) for detailed explanation of their C++ counterparts. + +Usage examples are shown below: + +```lua +-- Simple string. +-- +-- The "Experimental Lab" text will be extracted from this code by a script, +-- and will be available for translators. +-- When your Lua script runs, this function will search for translation of +-- "Experimental Lab" string and return either translated string, +-- or the original string if there was no translation found. +local location_name_translated = locale.gettext( "Experimental Lab" ) + +-- ERROR: you must call `gettext` with a string literal. +-- Calling it like this will make it so "Experimental Lab" is NOT extracted, +-- and translators won't see it when they translate the text. +local location_name_original = "Experimental Lab" +local location_name_translated = locale.gettext( location_name_original ) + +-- ERROR: don't alias the function under different name. +-- Calling it like this will make it so "Experimental Lab" is NOT extracted, +-- and translators won't see it when they translate the text. +local gettext_alt = locale.gettext +local location_name_translated = gettext_alt( "Experimental Lab" ) + +-- This, however, is fine. +local gettext = locale.gettext +local location_name_translated = gettext( "Experimental Lab" ) + +-- String with possible plural form. +-- Many languages have more than 2 plural forms with complex rules related to which one to use. +local item_display_name = locale.vgettext( "X-37 Prototype", "X-37 Prototypes", num_of_prototypes ) + +-- String with context +local text_1 = locale.pgettext("the one made of metal", "Spring") +local text_2 = locale.pgettext("the one that makes water", "Spring") +local text_3 = locale.pgettext("time of the year", "Spring") + +-- String with both context and plural forms. +local item_display_name = locale.vpgettext("the one made of metal", "Spring", "Springs", num_of_springs) + +--[[ + When some text is tricky and requires explanation, + it's common to place a special comment denoted with `~` to help translators. + The comment MUST BE right above the function call. +]] + +--~ This comment is good and will be visible for translators. +local ok = locale.gettext("Confusing text that needs explanation.") + +--~ ERROR: This comment is too far from gettext call and won't be extracted! +local not_ok = locale. + gettext("Confusing text that needs explanation.") + +local not_ok = locale.gettext( + --~ ERROR: This comment is in wrong place and won't be extracted! + "Confusing text that needs explanation." + ) + +--[[~ + ERROR: Multiline Lua comments can't be used as translator comments! + This comment won't be extracted! +]] +local ok = locale.gettext("Confusing text that needs explanation.") + +--~ If you need a multiline translator comment, +--~ just use 2 or more single-line comments. +--~ They'll be concatenated and shown as a single multi-line comment. +local ok = locale.gettext("Confusing text that needs explanation.") +``` + +## C++ layout + +Lua build can be enabled by passing `LUA=1` to the Makefile, or enabling `LUA` build switch in CMake +builds. Both msvc and android for simplicity always build with Lua **enabled**. + +### Lua source files + +To simplify build setup and improve portability we bundle `Lua 5.3.6` source code in `src/lua/` +directory and have the build systems compile it and link into the game executable and library for +tests. + +### Sol2 source files + +Sol2 makes it easy to bundle, we have `sol2 v3.3.0` single-header amalgamated version in `src/sol/` +and just include it as needed. The header is quite large, so the less source files include it the +better. + +- `sol/config.hpp` - Configuration header, we have a few options defined there +- `sol/forward.hpp` - Forward declarations, a lightweight header that should be included in game + headers instead of `sol/sol.hpp` +- `sol/sol.hpp` - Main sol2 header file, quite large, avoid including in game headers + +### Game source files + +All Lua-related game source files have the `catalua` prefix. + +If you want to add new bindings, consider looking at existing examples in `src/catalua_bindings.cpp` +and reading relevant part of Sol2 docs. + +- `catalua.h` (and `catalua.cpp`) - Main Lua interface. It's the only header most of the codebase + will have to include, and it provides a public interface that works in both `LUA=1` and `LUA=0` + builds ( in builds without Lua, most of the functions there are no-op ). +- `catalua_sol.h` and `catalua_sol_fwd.h` - Wrappers for `sol/sol.hpp` and `sol/forward.hpp` with + custom pragmas to make them compile. +- `catalua_bindings*` - Game Lua bindings live here. +- `catalua_console.h`(`.cpp`) - Ingame Lua console. +- `catalua_impl.h`(`.cpp`) - Implementation details for `catalua.h`(`.cpp`). +- `catalua_iuse_actor.h`(`.cpp`) - Lua-driven `iuse_actor`. +- `catalua_log.h`(`.cpp`) - In-memory logging for the console. +- `catalua_luna.h` - Usertype registration interface with automatic doc generation, aka `luna`. +- `catalua_luna_doc.h` - List of types registration through `luna` or exposed to its doc generator. +- `catalua_readonly.h`(`.cpp`) - Functions for marking Lua tables as read-only. +- `catalua_serde.h`(`.cpp`) - Lua table to/from JSON (de-)serialization. +- `catalua_type_operators.h` - Macro that helps with implementing bindings for string_ids + +### Adding new type to the doc generator without binding internals + +If a C++ type has not been registered in the doc generator, it will show up as +``. To mitigate this problem, you can add +`LUNA_VAL( your_type, "YourType" )` in `catalua_luna_doc.h`, and the generator will use `YourType` +string for argument type. + +### Binding new type to Lua + +First, we need to register the new type with the bindings system. It needs to be done for many +reasons, including so that the doc generator understands it, and the runtime can deserialize from +JSON any Lua table that contains that type. If you don't you'll get a compile error saying +`Type must implement luna_traits`. + +1. In `catala_luna_doc.h`, add declaration for your type. For example, if we're binding an imaginary + `horde` type (which is a `struct`), it will be a single line near the top of the file: + ```c++ + struct horde; + ``` + Complex templated types may need to actually pull in the relevant header, but please avoid it as + it heavily impacts compilation times. + +2. In the same file, register your type with the doc generator. Continuing with the `horde` example, + it's done like this: + ```c++ + LUNA_VAL( horde, "Horde" ); + ``` + While C++ types use all kinds of style for their names, on Lua side they all should be in + `CamelCase`. + +Now we can actually get to the details. The bindings are implemented in `catalua_bindings*.cpp` +files. They are spread out into multiple `.cpp` files to speed up compilation and make it easy to +navigate, so you can put yours into any existing `catalua_bindings*.cpp` file or make your own +similar file. They are also spread out into functions, for the same reasons. Let's register our +`horde` type, and put it in a new file and a new function: + +1. Add a new function declaration in `catalua_bindings.h`: + ```c++ + void reg_horde( sol::state &lua ); + ``` +2. Call the function in `reg_all_bindings` in `catalua_bindings.cpp`: + ```c++ + reg_horde( lua ); + ``` +3. Make a new file, `catalua_bindings_horde.cpp`, with the following contents: + ```c++ + #ifdef LUA + #include "catalua_bindings.h" + + #include "horde.h" // Replace with the header where your type is defined + + void cata::detail::reg_horde( sol::state &lua ) + { + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::constructors < + // Define your actual constructors here + horde(), + horde( const point & ), + horde( int, int ) + > () + ); + + // Register all needed members + luna::set( ut, "pos", &horde::pos ); + luna::set( ut, "size", &horde::size ); + + // Register all needed methods + luna::set_fx( ut, "move_to", &horde::move_to ); + luna::set_fx( ut, "update", &horde::update ); + luna::set_fx( ut, "get_printable_name", &horde::get_printable_name ); + + // Add (de-)serialization functions so we can carry + // our horde over the save/load boundary + reg_serde_functions( ut ); + + // Add more stuff like arithmetic operators, to_string operator, etc. + } + ``` +4. That's it. Your type is now visible in Lua under name `Horde`, and you can use the binded methods + and members. + +### Binding new enum to Lua + +Binding enums is similar to binding types. Let's bind an imaginary `horde_type` enum here: + +1. If enum does not have an explicitly defined container (the `: type` part after `enum name` in the + header where it's defined), you'll have to specify the container first, for example: + ```diff + // hordes.h + - enum class horde_type { + + enum class horde_type : int { + animals, + robots, + zombies + } + ``` +2. Add the declaration to `catalua_luna_doc.h` + ```c++ + enum horde_type : int; + ``` +3. Register it in `catalua_luna_doc.h` with + ```c++ + LUNA_ENUM( horde_type, "HordeType" ) + ``` +4. Ensure the enum implements the automatic conversion to/from `std::string`, see + `enum_conversions.h` for details. Some enums will already have it, but most won't. Usually it's + just a matter of specializing `enum_traits` for your enum `T` in the header, then defining + `io::enum_to_string` in the `.cpp` file with enum -> string conversion. Some enums won't have + the "last" value required for `enum_traits`. In that case, you'd have to add one: + ```diff + enum class horde_type : int { + animals, + robots, + - zombies + + zombies, + + num_horde_types + } + ``` + Note that this only works for "monotonic" enums, i.e. ones that start with 0 and don't skip any + values. In the example above, `animals` has implicit value of `0`, robots has implicit value of + `1` and `zombies` has implicit value of `2`, so we can easily add `num_horde_types`, which will + have correct and expected implicit value of `3`. +5. Bind enum fields in `reg_enums` function in `catalua_bindings.cpp`: + ```c++ + reg_enum( lua ); + ``` + This uses the automatic convertion from step 4, so we have equal names between JSON and Lua. + +### Binding new string_id or int_id to Lua + +Binding these can be done separately from binding `T` itself. + +1. Register your type `T` with the doc generator if you haven't already (see + [relevant docs](#adding-new-type-to-the-doc-generator-without-binding-internals)). +2. Replace `LUNA_VAL` from step 1 with `LUNA_ID`. +3. Ensure your type `T` implements operators `<` and `==`. It's usually easy implement them + manually, and can be done semi-automatically with macro `LUA_TYPE_OPS` found in + `catalua_type_operators.h`. +4. In `catalua_bindings_ids.cpp`, add the header where your type T is defined: + ```c++ + #include "your_type_definition.h" + ``` +5. In `reg_game_ids` function, register it like so: + ```c++ + reg_id( lua ); + ``` + +That `true` can be replaced with `false` if you only want to bind `string_id` and don't care +about (or can't implement) `int_id`. + +You may get linker errors at this stage, e.g. about `is_valid()` or `NULL_ID()` methods, which are +for various reasons not implemented forall string or int ids. In this case, you'll have to define +these manually, see relevant docs on `string_id` and `int_id` for more info. + +And that's it. Now, your type `T` will show up in Lua with `Raw` postfix, `string_id` will have +`Id` postfix, and `int_id` will have `IntId` postfix. As example, for +`LUNA_ID( horde, "Horde" )`, we'll get: + +- `horde` -> `HordeRaw` +- `string_id` -> `HordeId` +- `int_id` -> `HordeIntId` All type conversions between the 3 are implemented automatically + by the system. Actual fields and methods of `T` can be binded to Lua same way as usual. diff --git a/doc/MAGIC.md b/doc/MAGIC.md index a150b1df2540..3033dc18b5f6 100644 --- a/doc/MAGIC.md +++ b/doc/MAGIC.md @@ -1,4 +1,5 @@ # Spells, enchantments and other custom effects + - [Spells](#spells) - [Currently Implemented Effects and special rules](#currently-implemented-effects-and-special-rules) - [Spells that level up](#spells-that-level-up) @@ -40,7 +41,6 @@ - [ITEM\_ARMOR\_X](#item_armor_x) - [Examples](#examples) - # Spells In `data/mods/Magiclysm` there is a template spell, copied here for your perusal: @@ -94,86 +94,122 @@ In `data/mods/Magiclysm` there is a template spell, copied here for your perusal "sound_variant": "shockwave" // the sound variant } ``` -Most of the default values for the above are either 0 or "NONE", so you may leave out most of the values if they do not pertain to your spell. -When deciding values for some of these, it is important to note that some of the formulae are not linear. -For example, this is the formula for spell failure chance: +Most of the default values for the above are either 0 or "NONE", so you may leave out most of the +values if they do not pertain to your spell. -```( ( ( ( spell_level - spell_difficulty ) * 2 + intelligence + spellcraft_skill ) - 30 ) / 30 ) ^ 2``` +When deciding values for some of these, it is important to note that some of the formulae are not +linear. For example, this is the formula for spell failure chance: -Meaning a spell with difficulty 0 cast by a player with 8 intelligence, 0 spellcraft, and level 0 in the spell will have a 53% spell failure chance. -On the other hand, a player with 12 intelligence, 6 spellcraft, and level 6 in the same spell will have a 0% spell failure chance. +`( ( ( ( spell_level - spell_difficulty ) * 2 + intelligence + spellcraft_skill ) - 30 ) / 30 ) ^ 2` -However, experience gain is a little more complicated to calculate. The formula for how much experience you need to get to a level is below: +Meaning a spell with difficulty 0 cast by a player with 8 intelligence, 0 spellcraft, and level 0 in +the spell will have a 53% spell failure chance. On the other hand, a player with 12 intelligence, 6 +spellcraft, and level 6 in the same spell will have a 0% spell failure chance. -```e ^ ( ( level + 62.5 ) * 0.146661 ) ) - 6200``` +However, experience gain is a little more complicated to calculate. The formula for how much +experience you need to get to a level is below: + +`e ^ ( ( level + 62.5 ) * 0.146661 ) ) - 6200` #### Currently Implemented Effects and special rules -* "pain_split" - makes all of your limbs' damage even out. +- "pain_split" - makes all of your limbs' damage even out. + +- "move_earth" - "digs" at the target location. some terrain is not diggable this way. -* "move_earth" - "digs" at the target location. some terrain is not diggable this way. +- "target_attack" - deals damage to a target (ignores walls). Negative damage heals the target. If + "effect_str" is included, it will add that effect (defined elsewhere in json) to the targets if + able, to the body parts defined in affected_body_parts. Any aoe will manifest as a circular area + centered on the target, and will only deal damage to valid_targets. (aoe does not ignore walls) -* "target_attack" - deals damage to a target (ignores walls). Negative damage heals the target. If "effect_str" is included, it will add that effect (defined elsewhere in json) to the targets if able, to the body parts defined in affected_body_parts. -Any aoe will manifest as a circular area centered on the target, and will only deal damage to valid_targets. (aoe does not ignore walls) +- "projectile_attack" - similar to target_attack, except the projectile you shoot will stop short at + impassable terrain. If "effect_str" is included, it will add that effect (defined elsewhere in + json) to the targets if able, to the body parts defined in affected_body_parts. -* "projectile_attack" - similar to target_attack, except the projectile you shoot will stop short at impassable terrain. If "effect_str" is included, it will add that effect (defined elsewhere in json) to the targets if able, to the body parts defined in affected_body_parts. +- "cone_attack" - fires a cone toward the target up to your range. The arc of the cone in degrees is + aoe. Stops at walls. If "effect_str" is included, it will add that effect (defined elsewhere in + json) to the targets if able, to the body parts defined in affected_body_parts. -* "cone_attack" - fires a cone toward the target up to your range. The arc of the cone in degrees is aoe. Stops at walls. If "effect_str" is included, it will add that effect (defined elsewhere in json) to the targets if able, to the body parts defined in affected_body_parts. +- "line_attack" - fires a line with width aoe toward the target, being blocked by walls on the way. + If "effect_str" is included, it will add that effect (defined elsewhere in json) to the targets if + able, to the body parts defined in affected_body_parts. -* "line_attack" - fires a line with width aoe toward the target, being blocked by walls on the way. If "effect_str" is included, it will add that effect (defined elsewhere in json) to the targets if able, to the body parts defined in affected_body_parts. +- "spawn_item" - spawns an item that will disappear at the end of its duration. Default duration + is 0. Damage determines quantity. -* "spawn_item" - spawns an item that will disappear at the end of its duration. Default duration is 0. Damage determines quantity. +- "teleport_random" - teleports the player randomly range spaces with aoe variation -* "teleport_random" - teleports the player randomly range spaces with aoe variation +- "recover_energy" - recovers an energy source (defined in the effect_str, shown below) equal to + damage of the spell -* "recover_energy" - recovers an energy source (defined in the effect_str, shown below) equal to damage of the spell -- "MANA" -- "STAMINA" -- "FATIGUE" -- "PAIN" -- "BIONIC" +* "MANA" +* "STAMINA" +* "FATIGUE" +* "PAIN" +* "BIONIC" -* "ter_transform" - transform the terrain and furniture in an area centered at the target. The chance of any one of the points in the area of effect changing is one_in( damage ). The effect_str is the id of a ter_furn_transform. +- "ter_transform" - transform the terrain and furniture in an area centered at the target. The + chance of any one of the points in the area of effect changing is one_in( damage ). The effect_str + is the id of a ter_furn_transform. -* "vomit" - any creature within its area of effect will instantly vomit, if it's able to do so. +- "vomit" - any creature within its area of effect will instantly vomit, if it's able to do so. -* "timed_event" - adds a timed event to the player only. valid timed events: "help", "wanted", "robot_attack", "spawn_wyrms", "amigara", "roots_die", "temple_open", "temple_flood", "temple_spawn", "dim", "artifact_light" NOTE: This was added only for artifact active effects. support is limited, use at your own risk. +- "timed_event" - adds a timed event to the player only. valid timed events: "help", "wanted", + "robot_attack", "spawn_wyrms", "amigara", "roots_die", "temple_open", "temple_flood", + "temple_spawn", "dim", "artifact_light" NOTE: This was added only for artifact active effects. + support is limited, use at your own risk. -* "explosion" - an explosion is centered on the target, with power damage() and factor aoe()/10 +- "explosion" - an explosion is centered on the target, with power damage() and factor aoe()/10 -* "flashbang" - a flashbang effect is centered on the target, with poewr damage() and factor aoe()/10 +- "flashbang" - a flashbang effect is centered on the target, with poewr damage() and factor + aoe()/10 -* "mod_moves" - adds damage() moves to the target. can be negative to "freeze" the target for that amount of time +- "mod_moves" - adds damage() moves to the target. can be negative to "freeze" the target for that + amount of time -* "map" - maps the overmap centered on the player out to a radius of aoe() +- "map" - maps the overmap centered on the player out to a radius of aoe() -* "morale" - gives a morale effect to all npcs or avatar within aoe, with value damage(). decay_start is duration() / 10. +- "morale" - gives a morale effect to all npcs or avatar within aoe, with value damage(). + decay_start is duration() / 10. -* "charm_monster" - charms a monster that has less hp than damage() for approximately duration() +- "charm_monster" - charms a monster that has less hp than damage() for approximately duration() -* "mutate" - mutates the target(s). if effect_str is defined, mutates toward that category instead of picking at random. the "MUTATE_TRAIT" flag allows effect_str to be a specific trait instead of a category. damage() / 100 is the percent chance the mutation will be successful (a value of 10000 represents 100.00%) +- "mutate" - mutates the target(s). if effect_str is defined, mutates toward that category instead + of picking at random. the "MUTATE_TRAIT" flag allows effect_str to be a specific trait instead of + a category. damage() / 100 is the percent chance the mutation will be successful (a value of 10000 + represents 100.00%) -* "bash" - bashes the terrain at the target. uses damage() as the strength of the bash. +- "bash" - bashes the terrain at the target. uses damage() as the strength of the bash. -* "WONDER" - Unlike the above, this is not an "effect" but a "flag". This alters the behavior of the parent spell drastically: The spell itself doesn't cast, but its damage and range information is used in order to cast the extra_effects. N of the extra_effects will be chosen at random to be cast, where N is the current damage of the spell (stacks with RANDOM_DAMAGE flag) and the message of the spell cast by this spell will also be displayed. If this spell's message is not wanted to be displayed, make sure the message is an empty string. +- "WONDER" - Unlike the above, this is not an "effect" but a "flag". This alters the behavior of the + parent spell drastically: The spell itself doesn't cast, but its damage and range information is + used in order to cast the extra_effects. N of the extra_effects will be chosen at random to be + cast, where N is the current damage of the spell (stacks with RANDOM_DAMAGE flag) and the message + of the spell cast by this spell will also be displayed. If this spell's message is not wanted to + be displayed, make sure the message is an empty string. -* "RANDOM_TARGET" - A special spell flag (like wonder) that forces the spell to choose a random valid target within range instead of the caster choosing the target. This also affects extra_effects. +- "RANDOM_TARGET" - A special spell flag (like wonder) that forces the spell to choose a random + valid target within range instead of the caster choosing the target. This also affects + extra_effects. ##### For Spells that have an attack type, these are the available damage types: -* "fire" -* "acid" -* "bash" -* "bio" - internal damage such as poison -* "cold" -* "cut" -* "electric" -* "stab" -* "none" - this damage type goes through armor altogether. it is the default. + +- "fire" +- "acid" +- "bash" +- "bio" - internal damage such as poison +- "cold" +- "cut" +- "electric" +- "stab" +- "none" - this damage type goes through armor altogether. it is the default. #### Spells that level up -Spells that change effects as they level up must have a min and max effect and an increment. The min effect is what the spell will do at level 0, and the max effect is where it stops growing. The increment is how much it changes per level. For example: +Spells that change effects as they level up must have a min and max effect and an increment. The min +effect is what the spell will do at level 0, and the max effect is where it stops growing. The +increment is how much it changes per level. For example: ```json "min_range": 1, @@ -181,27 +217,32 @@ Spells that change effects as they level up must have a min and max effect and a "range_increment": 5, ``` -Min and max values must always have the same sign, but it can be negative eg. in the case of spells that use a negative 'recover' effect to cause pain or stamina damage. For example: +Min and max values must always have the same sign, but it can be negative eg. in the case of spells +that use a negative 'recover' effect to cause pain or stamina damage. For example: ```json - { - "id": "stamina_damage", - "type": "SPELL", - "name": "Tired", - "description": "decreases stamina", - "valid_targets": [ "hostile" ], - "min_damage": -2000, - "max_damage": -10000, - "damage_increment": -3000, - "max_level": 10, - "effect": "recover_energy", - "effect_str": "STAMINA" - } +{ + "id": "stamina_damage", + "type": "SPELL", + "name": "Tired", + "description": "decreases stamina", + "valid_targets": ["hostile"], + "min_damage": -2000, + "max_damage": -10000, + "damage_increment": -3000, + "max_level": 10, + "effect": "recover_energy", + "effect_str": "STAMINA" +} ``` ### Learning Spells -There are two ways of granting spells that is implemented: Mutating can grant a spell with the "spells_learned" field which also lets you specify the level granted. Otherwise you can learn a spell from an item through a use_action, which is also the only way to train a spell other than using it. Examples of both are shown below: +There are two ways of granting spells that is implemented: Mutating can grant a spell with the +"spells_learned" field which also lets you specify the level granted. Otherwise you can learn a +spell from an item through a use_action, which is also the only way to train a spell other than +using it. Examples of both are shown below: + ```C++ { "id": "DEBUG_spellbook", @@ -218,7 +259,9 @@ There are two ways of granting spells that is implemented: Mutating can grant a } }, ``` -You can study this spellbook for a rate of ~1 experience per turn depending on intelligence, spellcraft, and focus. + +You can study this spellbook for a rate of ~1 experience per turn depending on intelligence, +spellcraft, and focus. ```json "spells_learned": [ [ "debug_hp", 1 ], [ "debug_stamina", 1 ], [ "example_template", 1 ], [ "pain_split", 1 ] ], @@ -227,56 +270,74 @@ You can study this spellbook for a rate of ~1 experience per turn depending on i #### Spells in professions and NPC classes You can add a "spell" member to professions or an NPC class definition like so: + ```json "spells": [ { "id": "summon_zombie", "level": 0 }, { "id": "magic_missile", "level": 10 } ] ``` -NOTE: This makes it possible to learn spells that conflict with a class. It also does not give the prompt to gain the class. Be judicious upon adding this to a profession! +NOTE: This makes it possible to learn spells that conflict with a class. It also does not give the +prompt to gain the class. Be judicious upon adding this to a profession! #### Spells in monsters You can assign a spell as a special attack for a monster. + ```json { "type": "spell", "spell_id": "burning_hands", "spell_level": 10, "cooldown": 10 } ``` -* spell_id: the id for the spell being cast. -* spell_level: the level at which the spell is cast. Spells cast by monsters do not gain levels like player spells. -* cooldown: how often the monster can cast this spell + +- spell_id: the id for the spell being cast. +- spell_level: the level at which the spell is cast. Spells cast by monsters do not gain levels like + player spells. +- cooldown: how often the monster can cast this spell # Enchantments + Enchantments make it possible to specify custom effects provided by item, bionic or mutation. ## Fields + ### id + (string) Unique identifier for this enchantment. ### has -(string) How an enchantment determines if it is in the right location in order to qualify for being active. + +(string) How an enchantment determines if it is in the right location in order to qualify for being +active. This field is relevant only for items. Values: -* `HELD` (default) - when in your inventory -* `WIELD` - when wielded in your hand -* `WORN` - when worn as armor + +- `HELD` (default) - when in your inventory +- `WIELD` - when wielded in your hand +- `WORN` - when worn as armor ### condition -(string) How an enchantment determines if you are in the right environments in order for the enchantment to qualify for being active. + +(string) How an enchantment determines if you are in the right environments in order for the +enchantment to qualify for being active. Values: -* `ALWAYS` (default) - Always active -* `UNDERGROUND` - When the owner of the item is below Z-level 0 -* `UNDERWATER` - When the owner is in swimmable terrain -* `ACTIVE` - whenever the item, mutation, bionic, or whatever the enchantment is attached to is active. + +- `ALWAYS` (default) - Always active +- `UNDERGROUND` - When the owner of the item is below Z-level 0 +- `UNDERWATER` - When the owner is in swimmable terrain +- `ACTIVE` - whenever the item, mutation, bionic, or whatever the enchantment is attached to is + active. ### emitter -(string) Identifier of an emitter that's active as long as this enchantment is active. -Default: no emitter. + +(string) Identifier of an emitter that's active as long as this enchantment is active. Default: no +emitter. ### ench_effects + (array) Grants effects of specified intensity as long as this enchantment is active. Syntax for single entry: + ```C++ { // (required) Identifier of the effect @@ -288,9 +349,12 @@ Syntax for single entry: ``` ### hit_you_effect -(array) List of spells that may be cast when enchantment is active and character melee attacks a creature. + +(array) List of spells that may be cast when enchantment is active and character melee attacks a +creature. Syntax for single entry: + ```c++ { // (required) Identifier of the spell @@ -324,17 +388,22 @@ Syntax for single entry: ``` ### hit_me_effect -(array) List of spells that may be cast when enchantment is active and character gets melee attacked by a creature. + +(array) List of spells that may be cast when enchantment is active and character gets melee attacked +by a creature. Same syntax as for `hit_you_effect`. ### mutations + (array) List of mutations temporarily granted while enchantment is active. ### intermittent_activation + (object) Rules that specify random effects which occur while enchantment is active. Syntax: + ```c++ { // List of checks to run on every turn while enchantment is active. @@ -365,9 +434,11 @@ Syntax: ``` ### values + (array) List of miscellaneous character/item values to modify. Syntax for single entry: + ```c++ { // (required) Value ID to modify, refer to list below. @@ -383,156 +454,150 @@ Syntax for single entry: ``` Additive bonus is applied separately from multiplicative, like so: + ```c++ bonus = add + base_value * multiply ``` -Thus, a `multiply` value of -0.8 is -80%, and a `multiply` of 2.5 is +250%. -When modifying integer values, final bonus is rounded towards 0 (truncated). +Thus, a `multiply` value of -0.8 is -80%, and a `multiply` of 2.5 is +250%. When modifying integer +values, final bonus is rounded towards 0 (truncated). When multiple enchantments (e.g. one from an item and one from a bionic) modify the same value, -their bonuses are added together without rounding, then the sum is rounded (if necessary) -before being applied to the base value. +their bonuses are added together without rounding, then the sum is rounded (if necessary) before +being applied to the base value. -Since there's no limit on number of enchantments the character can have at a time, -the final calculated values have hardcoded bounds to prevent unintended behavior. +Since there's no limit on number of enchantments the character can have at a time, the final +calculated values have hardcoded bounds to prevent unintended behavior. #### IDs of modifiable values #### Character values ##### STRENGTH -Strength stat. -`base_value` here is the base stat value. -The final value cannot go below 0. + +Strength stat. `base_value` here is the base stat value. The final value cannot go below 0. ##### DEXTERITY -Dexterity stat. -`base_value` here is the base stat value. -The final value cannot go below 0. + +Dexterity stat. `base_value` here is the base stat value. The final value cannot go below 0. ##### PERCEPTION -Perception stat. -`base_value` here is the base stat value. -The final value cannot go below 0. + +Perception stat. `base_value` here is the base stat value. The final value cannot go below 0. ##### INTELLIGENCE -Intelligence stat. -`base_value` here is the base stat value. -The final value cannot go below 0. + +Intelligence stat. `base_value` here is the base stat value. The final value cannot go below 0. ##### SPEED -Character speed. -`base_value` here is character speed including pain/hunger/weight penalties. -Final speed value cannot go below 25% of base speed. + +Character speed. `base_value` here is character speed including pain/hunger/weight penalties. Final +speed value cannot go below 25% of base speed. ##### ATTACK_COST -Melee attack cost. The lower, the better. -`base_value` here is attack cost for given weapon including modifiers from stats and skills. -The final value cannot go below 25. + +Melee attack cost. The lower, the better. `base_value` here is attack cost for given weapon +including modifiers from stats and skills. The final value cannot go below 25. ##### MOVE_COST -Movement cost. -`base_value` here is tile movement cost including modifiers from clothing and traits. + +Movement cost. `base_value` here is tile movement cost including modifiers from clothing and traits. The final value cannot go below 20. ##### METABOLISM -Metabolic rate. -This modifier ignores `add` field. -`base_value` here is `PLAYER_HUNGER_RATE` modified by traits. -The final value cannot go below 0. + +Metabolic rate. This modifier ignores `add` field. `base_value` here is `PLAYER_HUNGER_RATE` +modified by traits. The final value cannot go below 0. ##### MANA_CAP -Mana capacity. -`base_value` here is character's base mana capacity modified by traits. -The final value cannot go below 0. + +Mana capacity. `base_value` here is character's base mana capacity modified by traits. The final +value cannot go below 0. ##### MANA_REGEN -Mana regeneration rate. -This modifier ignores `add` field. -`base_value` here is character's base mana gain rate modified by traits. -The final value cannot go below 0. + +Mana regeneration rate. This modifier ignores `add` field. `base_value` here is character's base +mana gain rate modified by traits. The final value cannot go below 0. ##### STAMINA_CAP -Stamina capacity. -This modifier ignores `add` field. -`base_value` here is character's base stamina capacity modified by traits. -The final value cannot go below 10% of `PLAYER_MAX_STAMINA`. + +Stamina capacity. This modifier ignores `add` field. `base_value` here is character's base stamina +capacity modified by traits. The final value cannot go below 10% of `PLAYER_MAX_STAMINA`. ##### STAMINA_REGEN -Stamina regeneration rate. -This modifier ignores `add` field. -`base_value` here is character's base stamina gain rate modified by mouth encumbrance. -The final value cannot go below 0. + +Stamina regeneration rate. This modifier ignores `add` field. `base_value` here is character's base +stamina gain rate modified by mouth encumbrance. The final value cannot go below 0. ##### THIRST -Thirst gain rate. -This modifier ignores `add` field. -`base_value` here is character's base thirst gain rate. -The final value cannot go below 0. + +Thirst gain rate. This modifier ignores `add` field. `base_value` here is character's base thirst +gain rate. The final value cannot go below 0. ##### FATIGUE -Fatigue gain rate. -This modifier ignores `add` field. -`base_value` here is character's base fatigue gain rate. -The final value cannot go below 0. + +Fatigue gain rate. This modifier ignores `add` field. `base_value` here is character's base fatigue +gain rate. The final value cannot go below 0. ##### BONUS_DODGE -Additional dodges per turn before dodge penalty kicks in. -`base_value` here is character's base dodges per turn before penalty (usually 1). -The final value can go below 0, which results in penalty to dodge roll. + +Additional dodges per turn before dodge penalty kicks in. `base_value` here is character's base +dodges per turn before penalty (usually 1). The final value can go below 0, which results in penalty +to dodge roll. ##### ARMOR_X -Incoming damage modifier. -Applied after Active Defense System bionic but before the damage is absorbed by items. -Note that `base_value` here is incoming damage value of corresponding type, -so positive `add` and greater than 1 `mul` will **increase** damage received by the character. -Each damage type has its own enchant value: -* `ARMOR_ACID` -* `ARMOR_BASH` -* `ARMOR_BIO` -* `ARMOR_BULLET` -* `ARMOR_COLD` -* `ARMOR_CUT` -* `ARMOR_ELEC` -* `ARMOR_HEAT` -* `ARMOR_STAB` + +Incoming damage modifier. Applied after Active Defense System bionic but before the damage is +absorbed by items. Note that `base_value` here is incoming damage value of corresponding type, so +positive `add` and greater than 1 `mul` will **increase** damage received by the character. Each +damage type has its own enchant value: + +- `ARMOR_ACID` +- `ARMOR_BASH` +- `ARMOR_BIO` +- `ARMOR_BULLET` +- `ARMOR_COLD` +- `ARMOR_CUT` +- `ARMOR_ELEC` +- `ARMOR_HEAT` +- `ARMOR_STAB` #### Item values ##### ITEM_ATTACK_COST -Attack cost (melee or throwing) for this item. -Ignores condition / location, and is always active. -`base_value` here is base item attack cost. -Note that the final value cannot go below 0. + +Attack cost (melee or throwing) for this item. Ignores condition / location, and is always active. +`base_value` here is base item attack cost. Note that the final value cannot go below 0. ##### ITEM_DAMAGE_X -Melee damage of this item. -Ignores condition / location, and is always active. -`base_value` here is base item damage of corresponding type. -Note that the final value cannot go below 0. -Only some damage types are supported: -* `ITEM_DAMAGE_BASH` -* `ITEM_DAMAGE_CUT` -* `ITEM_DAMAGE_STAB` + +Melee damage of this item. Ignores condition / location, and is always active. `base_value` here is +base item damage of corresponding type. Note that the final value cannot go below 0. Only some +damage types are supported: + +- `ITEM_DAMAGE_BASH` +- `ITEM_DAMAGE_CUT` +- `ITEM_DAMAGE_STAB` ##### ITEM_ARMOR_X -Incoming damage modifier for this item, applied before the damage is absorbed by the item. -Note that `base_value` here is incoming damage value of corresponding type, -so positive `add` and greater than 1 `mul` will **increase** damage received by the character. -Each damage type has its own enchant value: -* `ITEM_ARMOR_ACID` -* `ITEM_ARMOR_BASH` -* `ITEM_ARMOR_BIO` -* `ITEM_ARMOR_BULLET` -* `ITEM_ARMOR_COLD` -* `ITEM_ARMOR_CUT` -* `ITEM_ARMOR_ELEC` -* `ITEM_ARMOR_HEAT` -* `ITEM_ARMOR_STAB` +Incoming damage modifier for this item, applied before the damage is absorbed by the item. Note that +`base_value` here is incoming damage value of corresponding type, so positive `add` and greater than +1 `mul` will **increase** damage received by the character. Each damage type has its own enchant +value: + +- `ITEM_ARMOR_ACID` +- `ITEM_ARMOR_BASH` +- `ITEM_ARMOR_BIO` +- `ITEM_ARMOR_BULLET` +- `ITEM_ARMOR_COLD` +- `ITEM_ARMOR_CUT` +- `ITEM_ARMOR_ELEC` +- `ITEM_ARMOR_HEAT` +- `ITEM_ARMOR_STAB` ## Examples + ```json [ { @@ -555,13 +620,13 @@ Each damage type has its own enchant value: "id": "ENCH_ULTIMATE_ASSKICK", "has": "WIELD", "condition": "ALWAYS", - "ench_effects": [ { "effect": "invisibility", "intensity": 1 } ], - "hit_you_effect": [ { "id": "AEA_FIREBALL" } ], - "hit_me_effect": [ { "id": "AEA_HEAL" } ], - "mutations": [ "KILLER", "PARKOUR" ], - "values": [ { "value": "STRENGTH", "multiply": 1.1, "add": -5 } ], + "ench_effects": [{ "effect": "invisibility", "intensity": 1 }], + "hit_you_effect": [{ "id": "AEA_FIREBALL" }], + "hit_me_effect": [{ "id": "AEA_HEAL" }], + "mutations": ["KILLER", "PARKOUR"], + "values": [{ "value": "STRENGTH", "multiply": 1.1, "add": -5 }], "intermittent_activation": { - "effects": [ + "effects": [ { "frequency": "1 hour", "spell_effects": [ diff --git a/doc/MANUAL_OF_STYLE.md b/doc/MANUAL_OF_STYLE.md index 35d07fd30ab5..85b84c04a15a 100644 --- a/doc/MANUAL_OF_STYLE.md +++ b/doc/MANUAL_OF_STYLE.md @@ -1,10 +1,15 @@ 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 be followed by two spaces. If the sentence is the last in the block of text, there should be no spaces following it. +2. Use double sentence spacing after periods. This means that a period that ends a sentence should + be followed by two spaces. If the sentence is the last in the block of text, there should be no + spaces following it. 3. Use second person point of view (eg. "you"). -4. The names of traits, martial arts, and Compact Bionics Modules (CBM's) should be in title case. This means that each word should be capitalized unless it is an article, preposition or conjunction. +4. The names of traits, martial arts, and Compact Bionics Modules (CBM's) should be in title case. + This means that each word should be capitalized unless it is an article, preposition or + conjunction. 5. Items and entities with proper noun names should also be in title case. 6. All other item and entity names should be in all lower-case letters. 7. Use the serial comma (Oxford comma). -8. Use ellipsis character (…) instead of three dots (...). Replace instances of three periods with the dedicated Unicode character for ellipsis, namely U+2026. +8. Use ellipsis character (…) instead of three dots (...). Replace instances of three periods with + the dedicated Unicode character for ellipsis, namely U+2026. diff --git a/doc/MAPGEN.md b/doc/MAPGEN.md index 4dc9d8008bc6..490dc56a27fd 100644 --- a/doc/MAPGEN.md +++ b/doc/MAPGEN.md @@ -1,81 +1,82 @@ # MAPGEN -* [How buildings and terrain are generated](#how-buildings-and-terrain-are-generated) -* [Adding mapgen entries](#adding-mapgen-entries) - * [Methods](#methods) - * [Mapgen definition Placement](#mapgen-definition-placement) - * [Embedded mapgen](#embedded-mapgen) - * [Standalone mapgen](#standalone-mapgen) - * [Format and variables](#format-and-variables) - * [Define mapgen "method"](#define-mapgen-method) - * [Define overmap terrain with "om_terrain" value, array, or nested array](#define-overmap-terrain-with-om_terrain-value-array-or-nested-array) - * [Define mapgen "weight"](#define-mapgen-weight) - * [How "overmap_terrain" variables affect mapgen](#how-overmap_terrain-variables-affect-mapgen) - * [Limitations / TODO](#limitations--todo) -* [JSON object definition](#json-object-definition) - * [Fill terrain using "fill_ter"](#fill-terrain-using-fill_ter) - * [ASCII map using "rows" array](#ascii-map-using-rows-array) - * [Row terrains in "terrain"](#row-terrains-in-terrain) - * [Furniture symbols in "furniture" array](#furniture-symbols-in-furniture-array) - * [Set terrain, furniture, or traps with a "set" array](#set-terrain-furniture-or-traps-with-a-set-array) - * [Set things at a "point"](#set-things-at-a-point) - * [Set things in a "line"](#set-things-in-a-line) - * [Set things in a "square"](#set-things-in-a-square) - * [Spawn item or monster groups with "place_groups"](#spawn-item-or-monster-groups-with-place_groups) - * [Spawn monsters from a group with "monster"](#spawn-monsters-from-a-group-with-monster) - * [Spawn items from a group with "item"](#spawn-items-from-a-group-with-item) - * [Spawn a single monster with "place_monster"](#spawn-a-single-monster-with-place_monster) - * [Spawn an entire group of monsters with "place_monsters"](#spawn-an-entire-group-of-monsters-with-place_monsters) - * [Spawn specific items with a "place_item" array](#spawn-specific-items-with-a-place_item-array) - * [Extra map features with specials](#extra-map-features-with-specials) - * [Place smoke, gas, or blood with "fields"](#place-smoke-gas-or-blood-with-fields) - * [Place NPCs with "npcs"](#place-npcs-with-npcs) - * [Place signs with "signs"](#place-signs-with-signs) - * [Place a vending machine and items with "vendingmachines"](#place-a-vending-machine-and-items-with-vendingmachines) - * [Place a toilet with some amount of water with "toilets"](#place-a-toilet-with-some-amount-of-water-with-toilets) - * [Place a gas or diesel pump with some fuel with "gaspumps"](#place-a-gas-or-diesel-pump-with-some-fuel-with-gaspumps) - * [Place items from an item group with "items"](#place-items-from-an-item-group-with-items) - * [Place monsters from a monster group with "monsters"](#place-monsters-from-a-monster-group-with-monsters) - * [Place a vehicle by type or group with "vehicles"](#place-a-vehicle-by-type-or-group-with-vehicles) - * [Place a specific item with "item"](#place-a-specific-item-with-item) - * [Place a specific monster with "monster"](#place-a-specific-monster-with-monster) - * [Place a trap with "traps"](#place-a-trap-with-traps) - * [Place furniture with "furniture"](#place-furniture-with-furniture) - * [Place terrain with "terrain"](#place-terrain-with-terrain) - * [Place rubble and smash existing terrain with "rubble"](#place-rubble-and-smash-existing-terrain-with-rubble) - * [Place spilled liquids with "place_liquids"](#place-spilled-liquids-with-place_liquids) - * [Place a specific item or an item from a group with "loot"](#place-a-specific-item-or-an-item-from-a-group-with-loot) - * [Plant seeds in a planter with "sealed_item"](#plant-seeds-in-a-planter-with-sealed_item) - * [Place messages with "graffiti"](#place-messages-with-graffiti) - * [Place a zone for an NPC faction with "zones"](#place-a-zone-for-an-npc-faction-with-zones) - * [Translate terrain type with "translate_ter"](#translate-terrain-type-with-translate_ter) - * [Apply mapgen transformation with "ter_furn_transforms"](#apply-mapgen-transformation-with-ter_furn_transforms) - * [Rotate the map with "rotation"](#rotate-the-map-with-rotation) - * [Pre-load a base mapgen with "predecessor_mapgen"](#pre-load-a-base-mapgen-with-predecessor_mapgen) -* [Using update_mapgen](#using-update_mapgen) - * [Overmap tile specification](#overmap-tile-specification) - * ["assign_mission_target"](#assign_mission_target) - * ["om_terrain"](#om_terrain) -* [Mission specials](#mission-specials) - * ["target"](#target) +- [How buildings and terrain are generated](#how-buildings-and-terrain-are-generated) +- [Adding mapgen entries](#adding-mapgen-entries) + - [Methods](#methods) + - [Mapgen definition Placement](#mapgen-definition-placement) + - [Embedded mapgen](#embedded-mapgen) + - [Standalone mapgen](#standalone-mapgen) + - [Format and variables](#format-and-variables) + - [Define mapgen "method"](#define-mapgen-method) + - [Define overmap terrain with "om_terrain" value, array, or nested array](#define-overmap-terrain-with-om_terrain-value-array-or-nested-array) + - [Define mapgen "weight"](#define-mapgen-weight) + - [How "overmap_terrain" variables affect mapgen](#how-overmap_terrain-variables-affect-mapgen) + - [Limitations / TODO](#limitations--todo) +- [JSON object definition](#json-object-definition) + - [Fill terrain using "fill_ter"](#fill-terrain-using-fill_ter) + - [ASCII map using "rows" array](#ascii-map-using-rows-array) + - [Row terrains in "terrain"](#row-terrains-in-terrain) + - [Furniture symbols in "furniture" array](#furniture-symbols-in-furniture-array) + - [Set terrain, furniture, or traps with a "set" array](#set-terrain-furniture-or-traps-with-a-set-array) + - [Set things at a "point"](#set-things-at-a-point) + - [Set things in a "line"](#set-things-in-a-line) + - [Set things in a "square"](#set-things-in-a-square) + - [Spawn item or monster groups with "place_groups"](#spawn-item-or-monster-groups-with-place_groups) + - [Spawn monsters from a group with "monster"](#spawn-monsters-from-a-group-with-monster) + - [Spawn items from a group with "item"](#spawn-items-from-a-group-with-item) + - [Spawn a single monster with "place_monster"](#spawn-a-single-monster-with-place_monster) + - [Spawn an entire group of monsters with "place_monsters"](#spawn-an-entire-group-of-monsters-with-place_monsters) + - [Spawn specific items with a "place_item" array](#spawn-specific-items-with-a-place_item-array) + - [Extra map features with specials](#extra-map-features-with-specials) + - [Place smoke, gas, or blood with "fields"](#place-smoke-gas-or-blood-with-fields) + - [Place NPCs with "npcs"](#place-npcs-with-npcs) + - [Place signs with "signs"](#place-signs-with-signs) + - [Place a vending machine and items with "vendingmachines"](#place-a-vending-machine-and-items-with-vendingmachines) + - [Place a toilet with some amount of water with "toilets"](#place-a-toilet-with-some-amount-of-water-with-toilets) + - [Place a gas or diesel pump with some fuel with "gaspumps"](#place-a-gas-or-diesel-pump-with-some-fuel-with-gaspumps) + - [Place items from an item group with "items"](#place-items-from-an-item-group-with-items) + - [Place monsters from a monster group with "monsters"](#place-monsters-from-a-monster-group-with-monsters) + - [Place a vehicle by type or group with "vehicles"](#place-a-vehicle-by-type-or-group-with-vehicles) + - [Place a specific item with "item"](#place-a-specific-item-with-item) + - [Place a specific monster with "monster"](#place-a-specific-monster-with-monster) + - [Place a trap with "traps"](#place-a-trap-with-traps) + - [Place furniture with "furniture"](#place-furniture-with-furniture) + - [Place terrain with "terrain"](#place-terrain-with-terrain) + - [Place rubble and smash existing terrain with "rubble"](#place-rubble-and-smash-existing-terrain-with-rubble) + - [Place spilled liquids with "place_liquids"](#place-spilled-liquids-with-place_liquids) + - [Place a specific item or an item from a group with "loot"](#place-a-specific-item-or-an-item-from-a-group-with-loot) + - [Plant seeds in a planter with "sealed_item"](#plant-seeds-in-a-planter-with-sealed_item) + - [Place messages with "graffiti"](#place-messages-with-graffiti) + - [Place a zone for an NPC faction with "zones"](#place-a-zone-for-an-npc-faction-with-zones) + - [Translate terrain type with "translate_ter"](#translate-terrain-type-with-translate_ter) + - [Apply mapgen transformation with "ter_furn_transforms"](#apply-mapgen-transformation-with-ter_furn_transforms) + - [Rotate the map with "rotation"](#rotate-the-map-with-rotation) + - [Pre-load a base mapgen with "predecessor_mapgen"](#pre-load-a-base-mapgen-with-predecessor_mapgen) +- [Using update_mapgen](#using-update_mapgen) + - [Overmap tile specification](#overmap-tile-specification) + - ["assign_mission_target"](#assign_mission_target) + - ["om_terrain"](#om_terrain) +- [Mission specials](#mission-specials) + - ["target"](#target) # How buildings and terrain are generated -Cataclysm creates buildings and terrain on discovery via 'mapgen'; functions specific to an overmap terrain (the tiles -you see in `[m]`ap are also determined by overmap terrain). Overmap terrains ("oter") are defined in -`overmap_terrain.json`. +Cataclysm creates buildings and terrain on discovery via 'mapgen'; functions specific to an overmap +terrain (the tiles you see in `[m]`ap are also determined by overmap terrain). Overmap terrains +("oter") are defined in `overmap_terrain.json`. -By default, an oter has a single built-in mapgen function which matches the '"id"' in it's json entry (examples: -"house", "bank", etc). Multiple functions also possible. When a player moves into range of an area marked on the map as -a house, the game chooses semi-randomly from a list of functions for "house", picks one, and runs it, laying down walls -and adding items, monsters, rubber chickens and whatnot. This is all done in a fraction of a second (something to keep -in mind for later). +By default, an oter has a single built-in mapgen function which matches the '"id"' in it's json +entry (examples: "house", "bank", etc). Multiple functions also possible. When a player moves into +range of an area marked on the map as a house, the game chooses semi-randomly from a list of +functions for "house", picks one, and runs it, laying down walls and adding items, monsters, rubber +chickens and whatnot. This is all done in a fraction of a second (something to keep in mind for +later). -All mapgen functions build in a 24x24 tile area - even for large buildings; obtuse but surprisingly effective methods -are used to assemble giant 3x3 hotels, etc.. +All mapgen functions build in a 24x24 tile area - even for large buildings; obtuse but surprisingly +effective methods are used to assemble giant 3x3 hotels, etc.. -In order to make a world that's random and (somewhat) sensical, there are numerous rules and exceptions to them, which -are clarified below. +In order to make a world that's random and (somewhat) sensical, there are numerous rules and +exceptions to them, which are clarified below. There are three methods: @@ -83,33 +84,33 @@ There are three methods: - JSON object definition - Using update_mapgen - # Adding mapgen entries -One doesn't need to create a new `overmap_terrain` for a new variation of a building. For a custom gas station, defining a -mapgen entry and adding it to the "s_gas" mapgen list will add it to the random variations of gas station in the world. - -If you use an existing `overmap_terrain` and it has a roof or other z-level linked to its file, the other levels will be -generated with the ground floor. To avoid this, or add your own multiple z-levels, create an `overmap_terrain` with a -similar name (`s_gas_1`). +One doesn't need to create a new `overmap_terrain` for a new variation of a building. For a custom +gas station, defining a mapgen entry and adding it to the "s_gas" mapgen list will add it to the +random variations of gas station in the world. +If you use an existing `overmap_terrain` and it has a roof or other z-level linked to its file, the +other levels will be generated with the ground floor. To avoid this, or add your own multiple +z-levels, create an `overmap_terrain` with a similar name (`s_gas_1`). ## Methods -While adding mapgen as a c++ function is one of the fastest (and the most versatile) ways to generate procedural terrain -on the fly, this requires recompiling the game. - -Most of the existing c++ buildings have been moved to json and currently json mapping is the preferred method of adding -both content and mods. +While adding mapgen as a c++ function is one of the fastest (and the most versatile) ways to +generate procedural terrain on the fly, this requires recompiling the game. -* JSON: A set of json arrays and objects for defining stuff and things. Pros: Fastest to apply, mostly complete. Cons: - Not a programming language; no if statements or variables means instances of a particular json mapgen definition - will all be similar. Third party map editors are currently out of date. +Most of the existing c++ buildings have been moved to json and currently json mapping is the +preferred method of adding both content and mods. -* JSON support includes the use of nested mapgen, smaller mapgen chunks which override a portion of the linked mapgen. - This allows for greater variety in furniture, terrain and spawns within a single mapgen file. You can also link - mapgen files for multiple z-level buildings and multi-tile buildings. +- JSON: A set of json arrays and objects for defining stuff and things. Pros: Fastest to apply, + mostly complete. Cons: Not a programming language; no if statements or variables means instances + of a particular json mapgen definition will all be similar. Third party map editors are currently + out of date. +- JSON support includes the use of nested mapgen, smaller mapgen chunks which override a portion of + the linked mapgen. This allows for greater variety in furniture, terrain and spawns within a + single mapgen file. You can also link mapgen files for multiple z-level buildings and multi-tile + buildings. ## Mapgen definition Placement @@ -125,42 +126,40 @@ As `"mapgen": { ... }` only used in combination with the 'builtin' method: Do not use this, use standalone instead. - ### Standalone mapgen -As standalone `{ "type": "mapgen", ... }` objects in a .json inside data/json. Below is the fast food restaurant. +As standalone `{ "type": "mapgen", ... }` objects in a .json inside data/json. Below is the fast +food restaurant. ```json [ - { - "type": "mapgen", - "om_terrain": "s_restaurant_fast", - "weight": 250, - "method": "json", - "object": { - "//": "(see below)" - } + { + "type": "mapgen", + "om_terrain": "s_restaurant_fast", + "weight": 250, + "method": "json", + "object": { + "//": "(see below)" } + } ] ``` -Note how "om_terrain" matches the overmap "id". om_terrain is **required** for standalone mapgen entries. - +Note how "om_terrain" matches the overmap "id". om_terrain is **required** for standalone mapgen +entries. ## Format and variables -The above example only illustrate the mapgen entries, not the actual format for building stuff. However, the following -variables impact where and how often stuff gets applied: +The above example only illustrate the mapgen entries, not the actual format for building stuff. +However, the following variables impact where and how often stuff gets applied: - method - om_terrain - weight - ### Define mapgen "method" -**required** -Values: *json* - required +**required** Values: _json_ - required ``` "object": { (more json here) } @@ -170,8 +169,8 @@ Values: *json* - required **required for standalone** -The `om_terrain` value may be declared in one of three forms: with a single overmap terrain ID, with a list of IDs, or -with a nested list (of lists) of IDs. +The `om_terrain` value may be declared in one of three forms: with a single overmap terrain ID, with +a list of IDs, or with a nested list (of lists) of IDs. With the first form, simply give the ID of an overmap terrain from `overmap_terrain.json`: @@ -185,7 +184,8 @@ In the second form, provide a list of IDs: "om_terrain": [ "house", "house_base" ] ``` -This creates duplicate overmap terrains by applying the same json mapgen to each of the listed overmap terrain IDs. +This creates duplicate overmap terrains by applying the same json mapgen to each of the listed +overmap terrain IDs. The third option is a nested list: @@ -193,18 +193,20 @@ The third option is a nested list: "om_terrain": [ [ "oter_id_1a", "oter_id_1b", ... ], [ "oter_id_2a", "oter_id_2b", ... ], ... ] ``` -This form allows for multiple overmap terrains to be defined using a single json object, with the "rows" property -expanding in blocks of 24x24 characters to accommodate as many overmap terrains as are listed here. The terrain ids are -specified using a nested array of strings which represent the rows and columns of overmap terrain ids (found in -`overmap_terrain.json`) that are associated with the "rows" property described in section 2.1 of this document. +This form allows for multiple overmap terrains to be defined using a single json object, with the +"rows" property expanding in blocks of 24x24 characters to accommodate as many overmap terrains as +are listed here. The terrain ids are specified using a nested array of strings which represent the +rows and columns of overmap terrain ids (found in `overmap_terrain.json`) that are associated with +the "rows" property described in section 2.1 of this document. -Characters mapped using the "terrain", "furniture", or any of the special mappings ("items", "monsters", etc) will be -applied universally to all of the listed overmap terrains. +Characters mapped using the "terrain", "furniture", or any of the special mappings ("items", +"monsters", etc) will be applied universally to all of the listed overmap terrains. -Placing things using x/y coordinates ("place_monsters", "place_loot", "place_item", etc) works using the full extended -coordinates beyond 24x24. An important limitation is that ranged random coordinates (such as "x": `[ 10, 18 ]`) must not -cross the 24x24 terrain boundaries. Ranges such as `[ 0, 23 ]` and `[ 50, 70 ]` are valid, but `[ 0, 47 ]` and -`[ 15, 35 ]` are not because they extend beyond a single 24x24 block. +Placing things using x/y coordinates ("place_monsters", "place_loot", "place_item", etc) works using +the full extended coordinates beyond 24x24. An important limitation is that ranged random +coordinates (such as "x": `[ 10, 18 ]`) must not cross the 24x24 terrain boundaries. Ranges such as +`[ 0, 23 ]` and `[ 50, 70 ]` are valid, but `[ 0, 47 ]` and `[ 15, 35 ]` are not because they extend +beyond a single 24x24 block. Example: @@ -215,58 +217,56 @@ Example: ] ``` -In this example, the "rows" property should be 48x48, with each quadrant of 24x24 being associated with each of the four -apartments_mod_tower overmap terrain ids specified. - +In this example, the "rows" property should be 48x48, with each quadrant of 24x24 being associated +with each of the four apartments_mod_tower overmap terrain ids specified. ### Define mapgen "weight" -(optional) When the game randomly picks mapgen functions, each function's weight value determines how rare it is. 1000 -is the default, so adding something with weight '500' will make it appear 1/3 times, unless more functions are added. -(An insanely high value like 10000000 is useful for testing) +(optional) When the game randomly picks mapgen functions, each function's weight value determines +how rare it is. 1000 is the default, so adding something with weight '500' will make it appear 1/3 +times, unless more functions are added. (An insanely high value like 10000000 is useful for testing) -Values: number - *0 disables* +Values: number - _0 disables_ Default: 1000 - ## How "overmap_terrain" variables affect mapgen -"id" is used to determine the required "om_terrain" id for standalone, *except* when the following variables are set in -"overmap_terrain": +"id" is used to determine the required "om_terrain" id for standalone, _except_ when the following +variables are set in "overmap_terrain": -* "extras" - applies rare, random scenes after mapgen; helicopter crashes, etc -* "mondensity" - determines the default 'density' value for `"place_groups": [ { "monster": ...` (json). If this is not - set then place_monsters will not work without its own explicitly set density argument. +- "extras" - applies rare, random scenes after mapgen; helicopter crashes, etc +- "mondensity" - determines the default 'density' value for `"place_groups": [ { "monster": ...` + (json). If this is not set then place_monsters will not work without its own explicitly set + density argument. ## Limitations / TODO -* JSON: adding specific monster spawns are still WIP. -* The old mapgen.cpp system involved *The Biggest "if / else if / else if / .." Statement Known to Man*(tm), and is only - halfway converted to the "builtin" mapgen class. This means that while custom mapgen functions are allowed, the game - will cheerfully forget the default if one is added. -* TODO: Add to this list. - +- JSON: adding specific monster spawns are still WIP. +- The old mapgen.cpp system involved _The Biggest "if / else if / else if / .." Statement Known to + Man_(tm), and is only halfway converted to the "builtin" mapgen class. This means that while + custom mapgen functions are allowed, the game will cheerfully forget the default if one is added. +- TODO: Add to this list. # JSON object definition -The JSON object for a mapgen entry must include either `"fill_ter"`, or `"rows"` and `"terrain"`. All other fields are -optional. - +The JSON object for a mapgen entry must include either `"fill_ter"`, or `"rows"` and `"terrain"`. +All other fields are optional. ## Fill terrain using "fill_ter" -*required if "rows" is unset* Fill with the given terrain. + +_required if "rows" is unset_ Fill with the given terrain. Value: `"string"`: Valid terrain id from data/json/terrain.json Example: `"fill_ter": "t_grass"` - ## ASCII map using "rows" array -*required if "fill_ter" is unset* -Nested array of 24 (or 48) strings, each 24 (or 48) characters long, where each character is defined by "terrain" and -optionally "furniture" or other entries below. +_required if "fill_ter" is unset_ + +Nested array of 24 (or 48) strings, each 24 (or 48) characters long, where each character is defined +by "terrain" and optionally "furniture" or other entries below. Usage: @@ -274,22 +274,24 @@ Usage: "rows": [ "row1...", "row2...", ..., "row24..." ] ``` -Other parts can be linked with this map, for example one can place things like a gaspump (with gasoline) or a toilet -(with water) or items from an item group or fields at the square given by a character. - -Any character used here must have some definition elsewhere to indicate its purpose. Failing to do so is an error which -will be caught by running the tests. The tests will run automatically when you make a pull request for adding new maps -to the game. If you have defined `fill_ter` or you are writing nested mapgen, then there are a couple of exceptions. -The space and period characters (` ` and `.`) are permitted to have no definition and be used for 'background' in the -`rows`. - -As keys, you can use any Unicode characters which are not double-width. This includes for example most European -alphabets but not Chinese characters. If you intend to take advantage of this, ensure that your editor is saving the -file with a UTF-8 encoding. Accents are acceptable, even when using [combining -characters](https://en.wikipedia.org/wiki/Combining_character). No normalization is performed; comparison is done at -the raw bytes (code unit) level. Therefore, there are literally an infinite number of mapgen key characters available. -Please don't abuse this by using distinct characters that are visually indistinguishable, or which are so rare as to be -unlikely to render correctly for other developers. +Other parts can be linked with this map, for example one can place things like a gaspump (with +gasoline) or a toilet (with water) or items from an item group or fields at the square given by a +character. + +Any character used here must have some definition elsewhere to indicate its purpose. Failing to do +so is an error which will be caught by running the tests. The tests will run automatically when you +make a pull request for adding new maps to the game. If you have defined `fill_ter` or you are +writing nested mapgen, then there are a couple of exceptions. The space and period characters (`` +and `.`) are permitted to have no definition and be used for 'background' in the `rows`. + +As keys, you can use any Unicode characters which are not double-width. This includes for example +most European alphabets but not Chinese characters. If you intend to take advantage of this, ensure +that your editor is saving the file with a UTF-8 encoding. Accents are acceptable, even when using +[combining characters](https://en.wikipedia.org/wiki/Combining_character). No normalization is +performed; comparison is done at the raw bytes (code unit) level. Therefore, there are literally an +infinite number of mapgen key characters available. Please don't abuse this by using distinct +characters that are visually indistinguishable, or which are so rare as to be unlikely to render +correctly for other developers. Example: @@ -320,10 +322,10 @@ Example: " ,,,,,,,,,,,,,,,,,,,, ", " dd " ], - ``` ### Row terrains in "terrain" + **required by "rows"** Defines terrain ids for "rows", each key is a single character with a terrain id string @@ -366,10 +368,11 @@ Example: ``` ### Furniture symbols in "furniture" array + **optional** -Defines furniture ids for "rows" ( each character in rows is a terrain -or- terrain/furniture combo ). "f_null" means no -furniture but the entry can be left out +Defines furniture ids for "rows" ( each character in rows is a terrain -or- terrain/furniture combo +). "f_null" means no furniture but the entry can be left out Example: @@ -392,7 +395,9 @@ Example: ``` ## Set terrain, furniture, or traps with a "set" array -**optional** Specific commands to set terrain, furniture, traps, radiation, etc. Array is processed in order. + +**optional** Specific commands to set terrain, furniture, traps, radiation, etc. Array is processed +in order. Value: `[ array of {objects} ]: [ { "point": .. }, { "line": .. }, { "square": .. }, ... ]` @@ -406,29 +411,28 @@ Example: ] ``` -All X and Y values may be either a single integer between `0` and `23`, or an array of two integers `[ n1, n2 ]` (each -between `0` and `23`). If X or Y are set to an array, the result is a random number in that range (inclusive). In the above -examples, the furniture `"f_chair"` is always at coordinates `"x": 5, "y": 10`, but the trap `"tr_beartrap"` is -randomly repeated in the area `"x": [ 0, 23 ], "y": [ 5, 18 ]"`. +All X and Y values may be either a single integer between `0` and `23`, or an array of two integers +`[ n1, n2 ]` (each between `0` and `23`). If X or Y are set to an array, the result is a random +number in that range (inclusive). In the above examples, the furniture `"f_chair"` is always at +coordinates `"x": 5, "y": 10`, but the trap `"tr_beartrap"` is randomly repeated in the area +`"x": [ 0, 23 ], "y": [ 5, 18 ]"`. See terrain.json, furniture.json, and trap.json for "id" strings. - ### Set things at a "point" - Requires "point" type, and coordinates "x" and "y" - For "point" type "radiation", requires "amount" - For other types, requires "id" of terrain, furniture, or trap -| Field | Description -| --- | --- -| point | Allowed values: `"terrain"`, `"furniture"`, `"trap"`, `"radiation"` -| id | Terrain, furniture, or trap ID. Examples: `"id": "f_counter"`, `"id": "tr_beartrap"`. Omit for "radiation". -| x, y | X, Y coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. Example: `"x": 12, "y": [ 5, 15 ]` -| amount | Radiation amount. Value from `0-100`. -| chance | (optional) One-in-N chance to apply -| repeat | (optional) Value: `[ n1, n2 ]`. Spawn item randomly between `n1` and `n2` times. Only makes sense if the coordinates are random. Example: `[ 1, 3 ]` - repeat 1-3 times. - +| Field | Description | +| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| point | Allowed values: `"terrain"`, `"furniture"`, `"trap"`, `"radiation"` | +| id | Terrain, furniture, or trap ID. Examples: `"id": "f_counter"`, `"id": "tr_beartrap"`. Omit for "radiation". | +| x, y | X, Y coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. Example: `"x": 12, "y": [ 5, 15 ]` | +| amount | Radiation amount. Value from `0-100`. | +| chance | (optional) One-in-N chance to apply | +| repeat | (optional) Value: `[ n1, n2 ]`. Spawn item randomly between `n1` and `n2` times. Only makes sense if the coordinates are random. Example: `[ 1, 3 ]` - repeat 1-3 times. | ### Set things in a "line" @@ -437,20 +441,20 @@ See terrain.json, furniture.json, and trap.json for "id" strings. - For other types, requires "id" of terrain, furniture, or trap Example: + ```json { "line": "terrain", "id": "t_lava", "x": 5, "y": 5, "x2": 20, "y2": 20 } ``` -| Field | Description -| --- | --- -| line | Allowed values: `"terrain"`, `"furniture"`, `"trap"`, `"radiation"` -| id | Terrain, furniture, or trap ID. Examples: `"id": "f_counter"`, `"id": "tr_beartrap"`. Omit for "radiation". -| x, y | Start X, Y coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. Example: `"x": 12, "y": [ 5, 15 ]` -| x2, y2 | End X, Y coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. Example: `"x": 22, "y": [ 15, 20 ]` -| amount | Radiation amount. Value from `0-100`. -| chance | (optional) One-in-N chance to apply -| repeat | (optional) Value: `[ n1, n2 ]`. Spawn item randomly between `n1` and `n2` times. Only makes sense if the coordinates are random. Example: `[ 1, 3 ]` - repeat 1-3 times. - +| Field | Description | +| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| line | Allowed values: `"terrain"`, `"furniture"`, `"trap"`, `"radiation"` | +| id | Terrain, furniture, or trap ID. Examples: `"id": "f_counter"`, `"id": "tr_beartrap"`. Omit for "radiation". | +| x, y | Start X, Y coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. Example: `"x": 12, "y": [ 5, 15 ]` | +| x2, y2 | End X, Y coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. Example: `"x": 22, "y": [ 15, 20 ]` | +| amount | Radiation amount. Value from `0-100`. | +| chance | (optional) One-in-N chance to apply | +| repeat | (optional) Value: `[ n1, n2 ]`. Spawn item randomly between `n1` and `n2` times. Only makes sense if the coordinates are random. Example: `[ 1, 3 ]` - repeat 1-3 times. | ### Set things in a "square" @@ -458,160 +462,169 @@ Example: - For "square" type "radiation", requires "amount" - For other types, requires "id" of terrain, furniture, or trap -The "square" arguments are the same as for "line", but "x", "y" and "x2", "y2" define opposite corners. +The "square" arguments are the same as for "line", but "x", "y" and "x2", "y2" define opposite +corners. Example: + ```json -{ "square": "radiation", "amount": 10, "x": [ 0, 5 ], "y": [ 0, 5 ], "x2": [ 18, 23 ], "y2": [ 18, 23 ] } +{ "square": "radiation", "amount": 10, "x": [0, 5], "y": [0, 5], "x2": [18, 23], "y2": [18, 23] } ``` -| Field | Description -| --- | --- -| square | Allowed values: `"terrain"`, `"furniture"`, `"trap"`, `"radiation"` -| id | Terrain, furniture, or trap ID. Examples: `"id": "f_counter"`, `"id": "tr_beartrap"`. Omit for "radiation". -| x, y | Top-left corner of square. -| x2, y2 | Bottom-right corner of square. - +| Field | Description | +| ------ | ----------------------------------------------------------------------------------------------------------- | +| square | Allowed values: `"terrain"`, `"furniture"`, `"trap"`, `"radiation"` | +| id | Terrain, furniture, or trap ID. Examples: `"id": "f_counter"`, `"id": "tr_beartrap"`. Omit for "radiation". | +| x, y | Top-left corner of square. | +| x2, y2 | Bottom-right corner of square. | ## Spawn item or monster groups with "place_groups" + **optional** Spawn items or monsters from item_groups.json and monster_groups.json Value: `[ array of {objects} ]: [ { "monster": ... }, { "item": ... }, ... ]` ### Spawn monsters from a group with "monster" -| Field | Description -| --- | --- -| monster | (required) Value: `"MONSTER_GROUP"`. The monster group id, which picks random critters from a list -| x, y | (required) Spawn coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. -| density | (optional) Floating-point multiplier to "chance" (see below). -| chance | (optional) One-in-N chance to spawn +| Field | Description | +| ------- | ------------------------------------------------------------------------------------------------------------ | +| monster | (required) Value: `"MONSTER_GROUP"`. The monster group id, which picks random critters from a list | +| x, y | (required) Spawn coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. | +| density | (optional) Floating-point multiplier to "chance" (see below). | +| chance | (optional) One-in-N chance to spawn | Example: ```json -{ "monster": "GROUP_ZOMBIE", "x": [ 13, 15 ], "y": 15, "chance": 10 } +{ "monster": "GROUP_ZOMBIE", "x": [13, 15], "y": 15, "chance": 10 } ``` -When using a range for `"x"` or `"y"`, the minimum and maximum values will be used in creating rectangle coordinates to -be used by `map::place_spawns`. Each monster generated from the monster group will be placed in a different random -location within the rectangle. The values in the above example will produce a rectangle for `map::place_spawns` from ( -13, 15 ) to ( 15, 15 ) inclusive. - -The optional "density" is a floating-point multipier to the "chance" value. If the result is bigger than 100% it -gurantees one spawn point for every 100% and the rest is evaluated by chance (one added or not). Then the monsters are -spawned according to their spawn-point cost "cost_multiplier" defined in the monster groups. Additionally all overmap -densities within a square of raduis 3 (7x7 around player - exact value in mapgen.cpp/MON_RADIUS macro) are added to -this. The "pack_size" modifier in monstergroups is a random multiplier to the rolled spawn point amount. - +When using a range for `"x"` or `"y"`, the minimum and maximum values will be used in creating +rectangle coordinates to be used by `map::place_spawns`. Each monster generated from the monster +group will be placed in a different random location within the rectangle. The values in the above +example will produce a rectangle for `map::place_spawns` from ( 13, 15 ) to ( 15, 15 ) inclusive. +The optional "density" is a floating-point multipier to the "chance" value. If the result is bigger +than 100% it gurantees one spawn point for every 100% and the rest is evaluated by chance (one added +or not). Then the monsters are spawned according to their spawn-point cost "cost_multiplier" defined +in the monster groups. Additionally all overmap densities within a square of raduis 3 (7x7 around +player - exact value in mapgen.cpp/MON_RADIUS macro) are added to this. The "pack_size" modifier in +monstergroups is a random multiplier to the rolled spawn point amount. ### Spawn items from a group with "item" -| Field | Description -| --- | --- -| item | (required) Value: "ITEM_GROUP". The item group id, which picks random stuff from a list. -| x, y | (required) Spawn coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. -| chance | (required) Percentage chance to spawn. +| Field | Description | +| ------ | ------------------------------------------------------------------------------------------------------------ | +| item | (required) Value: "ITEM_GROUP". The item group id, which picks random stuff from a list. | +| x, y | (required) Spawn coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. | +| chance | (required) Percentage chance to spawn. | Example: ```json -{ "item": "livingroom", "x": 12, "y": [ 5, 15 ], "chance": 50 } +{ "item": "livingroom", "x": 12, "y": [5, 15], "chance": 50 } ``` -When using a range for `"x"` or `"y"`, the minimum and maximum values will be used in creating rectangle coordinates to -be used by `map::place_items`. Each item from the item group will be placed in a different random location within the -rectangle. These values in the above example will produce a rectangle for map::place_items from ( 12, 5 ) to ( 12, 15 ) -inclusive. - +When using a range for `"x"` or `"y"`, the minimum and maximum values will be used in creating +rectangle coordinates to be used by `map::place_items`. Each item from the item group will be placed +in a different random location within the rectangle. These values in the above example will produce +a rectangle for map::place_items from ( 12, 5 ) to ( 12, 15 ) inclusive. ## Spawn a single monster with "place_monster" -**optional** Spawn single monster. Either specific monster or a random monster from a monster group. Is affected by spawn density game setting. +**optional** Spawn single monster. Either specific monster or a random monster from a monster group. +Is affected by spawn density game setting. Value: `[ array of {objects} ]: [ { "monster": ... } ]` -| Field | Description -| --- | --- -| monster | ID of the monster to spawn. -| group | ID of the monster group from which the spawned monster is selected. `monster` and `group` should not be used together. `group` will act over `monster`. -| x, y | Spawn coordinates ( specific or area rectangle ). Value: 0-23 or `[ 0-23, 0-23 ]` - random value between `[ a, b ]`. -| chance | Percentage chance to do spawning. If repeat is used each repeat has separate chance. -| repeat | The spawning is repeated this many times. Can be a number or a range. -| pack_size | How many monsters are spawned. Can be single number or range like `[1-4]`. Is affected by the chance and spawn density. Ignored when spawning from a group. -| one_or_none | Do not allow more than one to spawn due to high spawn density. If repeat is not defined or pack size is defined this defaults to true true, otherwise this defaults to false. Ignored when spawning from a group. -| friendly | Set true to make the monster friendly. Default false. -| name | Extra name to display on the monster. -| target | Set to true to make this into mission target. Only works when the monster is spawned from a mission. - -Note that high spawn density game setting can cause extra monsters to spawn when `monster` is used. When `group` is used -only one monster will spawn. - -When using a range for `"x"` or `"y"`, the minimum and maximum values will be used in creating rectangle coordinates to -be used by `map::place_spawns`. Each monster generated from the monster group will be placed in a different random -location within the rectangle. Example: `"x": 12, "y": [ 5, 15 ]` - these values will produce a rectangle for -`map::place_spawns` from ( 12, 5 ) to ( 12, 15 ) inclusive. +| Field | Description | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| monster | ID of the monster to spawn. | +| group | ID of the monster group from which the spawned monster is selected. `monster` and `group` should not be used together. `group` will act over `monster`. | +| x, y | Spawn coordinates ( specific or area rectangle ). Value: 0-23 or `[ 0-23, 0-23 ]` - random value between `[ a, b ]`. | +| chance | Percentage chance to do spawning. If repeat is used each repeat has separate chance. | +| repeat | The spawning is repeated this many times. Can be a number or a range. | +| pack_size | How many monsters are spawned. Can be single number or range like `[1-4]`. Is affected by the chance and spawn density. Ignored when spawning from a group. | +| one_or_none | Do not allow more than one to spawn due to high spawn density. If repeat is not defined or pack size is defined this defaults to true true, otherwise this defaults to false. Ignored when spawning from a group. | +| friendly | Set true to make the monster friendly. Default false. | +| name | Extra name to display on the monster. | +| target | Set to true to make this into mission target. Only works when the monster is spawned from a mission. | + +Note that high spawn density game setting can cause extra monsters to spawn when `monster` is used. +When `group` is used only one monster will spawn. + +When using a range for `"x"` or `"y"`, the minimum and maximum values will be used in creating +rectangle coordinates to be used by `map::place_spawns`. Each monster generated from the monster +group will be placed in a different random location within the rectangle. Example: +`"x": 12, "y": [ 5, 15 ]` - these values will produce a rectangle for `map::place_spawns` from ( 12, +5 ) to ( 12, 15 ) inclusive. Example: + ```json "place_monster": [ { "group": "GROUP_REFUGEE_BOSS_ZOMBIE", "name": "Sean McLaughlin", "x": 10, "y": 10, "target": true } ] ``` -This places a single random monster from group "GROUP_REFUGEE_BOSS_ZOMBIE", sets the name to "Sean McLaughlin", spawns -the monster at coordinate (10, 10) and also sets the monster as the target of this mission. +This places a single random monster from group "GROUP_REFUGEE_BOSS_ZOMBIE", sets the name to "Sean +McLaughlin", spawns the monster at coordinate (10, 10) and also sets the monster as the target of +this mission. Example: + ```json "place_monster": [ { "monster": "mon_secubot", "x": [ 7, 18 ], "y": [ 7, 18 ], "chance": 30, "repeat": [1, 3] } ] ``` -This places "mon_secubot" at random coordinate (7-18, 7-18). The monster is placed with 30% probablity. The placement is -repeated by random number of times `[1-3]`. - +This places "mon_secubot" at random coordinate (7-18, 7-18). The monster is placed with 30% +probablity. The placement is repeated by random number of times `[1-3]`. ## Spawn an entire group of monsters with "place_monsters" -Using `place_monsters` to spawn a group of monsters works in a similar fashion to `place_monster`. The key difference is that `place_monsters` guarantees that each valid entry in the group is spawned. It is strongly advised that you avoid using this flag with larger monster groups, as the total number of spawns is quite difficult to control. -|Field|Description | -|--|--| -| monster | The ID of the monster group that you wish to spawn | -| x, y | Spawn coordinates ( specific or area rectangle ). Value: 0-23 or `[ 0-23, 0-23 ]` - random value between `[ a, b ]`. -| chance | Represents a 1 in N chance that the entire group will spawn. This is done once for each repeat. If this dice roll fails, the entire group specified will not spawn. Leave blank to guarantee spawns. -| repeat | The spawning is repeated this many times. Can be a number or a range. Again, this represents the number of times the group will be spawned. -| density | This number is multiplied by the spawn density of the world the player is in and then probabilistically rounded to determine how many times to spawn the group. This is done for each time the spawn is repeated. For instance, if the final multiplier from this calculation ends up being `2`, and the repeat value is `6`, then the group will be spawned `2 * 6` or 12 times. +Using `place_monsters` to spawn a group of monsters works in a similar fashion to `place_monster`. +The key difference is that `place_monsters` guarantees that each valid entry in the group is +spawned. It is strongly advised that you avoid using this flag with larger monster groups, as the +total number of spawns is quite difficult to control. +| Field | Description | +| ------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| monster | The ID of the monster group that you wish to spawn | +| x, y | Spawn coordinates ( specific or area rectangle ). Value: 0-23 or `[ 0-23, 0-23 ]` - random value between `[ a, b ]`. | +| chance | Represents a 1 in N chance that the entire group will spawn. This is done once for each repeat. If this dice roll fails, the entire group specified will not spawn. Leave blank to guarantee spawns. | +| repeat | The spawning is repeated this many times. Can be a number or a range. Again, this represents the number of times the group will be spawned. | +| density | This number is multiplied by the spawn density of the world the player is in and then probabilistically rounded to determine how many times to spawn the group. This is done for each time the spawn is repeated. For instance, if the final multiplier from this calculation ends up being `2`, and the repeat value is `6`, then the group will be spawned `2 * 6` or 12 times. | ## Spawn specific items with a "place_item" array -**optional** A list of *specific* things to add. WIP: Monsters and vehicles will be here too + +**optional** A list of _specific_ things to add. WIP: Monsters and vehicles will be here too Value: `[ array of {objects} ]: [ { "item", ... }, ... ]` Example: + ```json "place_item": [ { "item": "weed", "x": 14, "y": 15, "amount": [ 10, 20 ], "repeat": [1, 3], "chance": 20 } ] ``` -| Field | Description -| --- | --- -| item | (required) ID of the item to spawn -| x, y | (required) Spawn coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. -| amount | (required) Number of items to spawn. Single integer, or range `[ a, b ]` for a random value in that range. -| chance | (optional) One-in-N chance to spawn item. -| repeat | (optional) Value: `[ n1, n2 ]`. Spawn item randomly between `n1` and `n2` times. Only makes sense if the coordinates are random. Example: `[ 1, 3 ]` - repeat 1-3 times. - +| Field | Description | +| ------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | +| item | (required) ID of the item to spawn | +| x, y | (required) Spawn coordinates. Value from `0-23`, or range `[ 0-23, 0-23 ]` for a random value in that range. | +| amount | (required) Number of items to spawn. Single integer, or range `[ a, b ]` for a random value in that range. | +| chance | (optional) One-in-N chance to spawn item. | +| repeat | (optional) Value: `[ n1, n2 ]`. Spawn item randomly between `n1` and `n2` times. Only makes sense if the coordinates are random. Example: `[ 1, 3 ]` - repeat 1-3 times. | ## Extra map features with specials + **optional** Special map features that do more than just placing furniture / terrain. -Specials can be defined either via a mapping like the terrain / furniture mapping using the "rows" entry above or -through their exact location by its coordinates. +Specials can be defined either via a mapping like the terrain / furniture mapping using the "rows" +entry above or through their exact location by its coordinates. The mapping is defined with a json object like this: @@ -624,13 +637,13 @@ The mapping is defined with a json object like this: } ``` -`""` is one of the types listed below. `` is a json object with content specific to -the special type. Some types require no data at all or all their data is optional, an empty object is enough for those -specials. You can define as many mapping as you want. +`""` is one of the types listed below. `` is a json object with +content specific to the special type. Some types require no data at all or all their data is +optional, an empty object is enough for those specials. You can define as many mapping as you want. -Each mapping can be an array, for things that can appear several times on the tile (e.g. items, fields) each entry of -the array is applied in order. For traps, furniture and terrain, one entry is randomly chosen (all entries have the same -chances) and applied. +Each mapping can be an array, for things that can appear several times on the tile (e.g. items, +fields) each entry of the array is applied in order. For traps, furniture and terrain, one entry is +randomly chosen (all entries have the same chances) and applied. Example (places grass at 2/3 of all '.' square and dirt at 1/3 of them): @@ -640,8 +653,9 @@ Example (places grass at 2/3 of all '.' square and dirt at 1/3 of them): } ``` -It is also possible to specify the number of instances (and consequently their chance) directly, which is particularly -useful for rare occurrences (rather than repeating the common value many times): +It is also possible to specify the number of instances (and consequently their chance) directly, +which is particularly useful for rare occurrences (rather than repeating the common value many +times): ```json "terrain" : { @@ -649,7 +663,6 @@ useful for rare occurrences (rather than repeating the common value many times): } ``` - Example (places a blood and a bile field on each '.' square): ```json @@ -659,6 +672,7 @@ Example (places a blood and a bile field on each '.' square): ``` Or define the mappings for one character at once: + ```json "mapping" : { ".": { @@ -669,9 +683,11 @@ Or define the mappings for one character at once: } } ``` + This might be more useful if you want to put many different type of things on one place. Defining specials through their specific location: + ``` "place_" : { { "x": , "y": , }, @@ -679,10 +695,12 @@ Defining specials through their specific location: } ``` -`` and `` define where the special is placed (x is horizontal, y vertical). Valid value are in the range 0..23, -min-max values are also supported: `"x": [ 0, 23 ], "y": [ 0, 23 ]` places the special anyway on the map. +`` and `` define where the special is placed (x is horizontal, y vertical). Valid value are in +the range 0..23, min-max values are also supported: `"x": [ 0, 23 ], "y": [ 0, 23 ]` places the +special anyway on the map. -Example with mapping (the characters `"O"` and `";"` should appear in the rows array where the specials should appear): +Example with mapping (the characters `"O"` and `";"` should appear in the rows array where the +specials should appear): ```json "gaspumps": { @@ -693,7 +711,8 @@ Example with mapping (the characters `"O"` and `";"` should appear in the rows a } ``` -The amount of water to be placed in toilets is optional, an empty entry is therefor completely valid. +The amount of water to be placed in toilets is optional, an empty entry is therefor completely +valid. Example with coordinates: @@ -707,12 +726,15 @@ Example with coordinates: ``` Terrain, furniture and traps can specified as a single string, not a json object: + ```json "traps" : { ".": "tr_beartrap" } ``` + Same as + ```json "traps" : { ".": { "trap": "tr_beartrap" } @@ -721,13 +743,12 @@ Same as ### Place smoke, gas, or blood with "fields" -| Field | Description -| --- | --- -| field | (required, string) the field type (e.g. `"fd_blood"`, `"fd_smoke"`) -| density | (optional, integer) field density. Defaults to 1. Possible values are 1, 2, or 3. -| intensity | (optional, integer) how concentrated the field is, from 1 to 3 or more. See `data/json/field_type.json` -| age | (optional, integer) field age. Defaults to 0. - +| Field | Description | +| --------- | ------------------------------------------------------------------------------------------------------- | +| field | (required, string) the field type (e.g. `"fd_blood"`, `"fd_smoke"`) | +| density | (optional, integer) field density. Defaults to 1. Possible values are 1, 2, or 3. | +| intensity | (optional, integer) how concentrated the field is, from 1 to 3 or more. See `data/json/field_type.json` | +| age | (optional, integer) field age. Defaults to 0. | ### Place NPCs with "npcs" @@ -737,18 +758,17 @@ Example: "npcs": { "A": { "class": "NC_REFUGEE", "target": true, "add_trait": "ASTHMA" } } ``` -| Field | Description -| --- | --- -| class | (required, string) the npc class id, see `data/json/npcs/npc.json` or define your own npc class. -| target | (optional, bool) this NPC is a mission target. Only valid for `update_mapgen`. -| add_trait | (optional, string or string array) this NPC gets these traits, in addition to any from the class definition. - +| Field | Description | +| --------- | ------------------------------------------------------------------------------------------------------------ | +| class | (required, string) the npc class id, see `data/json/npcs/npc.json` or define your own npc class. | +| target | (optional, bool) this NPC is a mission target. Only valid for `update_mapgen`. | +| add_trait | (optional, string or string array) this NPC gets these traits, in addition to any from the class definition. | ### Place signs with "signs" -Places a sign (furniture `f_sign`) with a message written on it. Either "signage" or "snippet" must be defined. The -message may include tags like ``, ``, and `` that will insert a randomly generated -name, or `` that will insert the nearest city name. +Places a sign (furniture `f_sign`) with a message written on it. Either "signage" or "snippet" must +be defined. The message may include tags like ``, ``, and `` +that will insert a randomly generated name, or `` that will insert the nearest city name. Example: @@ -756,81 +776,76 @@ Example: "signs": { "P": { "signage": "Subway map: stop" } } ``` -| Field | Description -| --- | --- -| signage | (optional, string) the message that should appear on the sign. -| snippet | (optional, string) a category of snippets that can appear on the sign. - +| Field | Description | +| ------- | ---------------------------------------------------------------------- | +| signage | (optional, string) the message that should appear on the sign. | +| snippet | (optional, string) a category of snippets that can appear on the sign. | ### Place a vending machine and items with "vendingmachines" -Places a vending machine (furniture) and fills it with items from an item group. The machine can sometimes spawn as broken one. - -| Field | Description -| --- | --- -| item_group | (optional, string) the item group that is used to create items inside the machine. It defaults to either "vending_food" or "vending_drink" (randomly chosen). +Places a vending machine (furniture) and fills it with items from an item group. The machine can +sometimes spawn as broken one. +| Field | Description | +| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| item_group | (optional, string) the item group that is used to create items inside the machine. It defaults to either "vending_food" or "vending_drink" (randomly chosen). | ### Place a toilet with some amount of water with "toilets" Places a toilet (furniture) and adds water to it. -| Field | Description -| --- | --- -| amount | (optional, integer or min/max array) the amount of water to be placed in the toilet. - +| Field | Description | +| ------ | ------------------------------------------------------------------------------------ | +| amount | (optional, integer or min/max array) the amount of water to be placed in the toilet. | ### Place a gas or diesel pump with some fuel with "gaspumps" Places a gas pump with gasoline (or sometimes diesel) in it. -| Field | Description -| --- | --- -| amount | (optional, integer or min/max array) the amount of fuel to be placed in the pump. -| fuel | (optional, string: "gasoline" or "diesel") the type of fuel to be placed in the pump. - +| Field | Description | +| ------ | ------------------------------------------------------------------------------------- | +| amount | (optional, integer or min/max array) the amount of fuel to be placed in the pump. | +| fuel | (optional, string: "gasoline" or "diesel") the type of fuel to be placed in the pump. | ### Place items from an item group with "items" -| Field | Description -| --- | --- -| item | (required, string or itemgroup object) the item group to use. -| chance | (optional, integer or min/max array) x in 100 chance that a loop will continue to spawn items from the group (which itself may spawn multiple items or not depending on its type, see `ITEM_SPAWN.md`), unless the chance is 100, in which case it will trigger the item group spawn exactly 1 time (see `map::place_items`). -| repeat | (optional, integer or min/max array) the number of times to repeat this placement, default is 1. - +| Field | Description | +| ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| item | (required, string or itemgroup object) the item group to use. | +| chance | (optional, integer or min/max array) x in 100 chance that a loop will continue to spawn items from the group (which itself may spawn multiple items or not depending on its type, see `ITEM_SPAWN.md`), unless the chance is 100, in which case it will trigger the item group spawn exactly 1 time (see `map::place_items`). | +| repeat | (optional, integer or min/max array) the number of times to repeat this placement, default is 1. | ### Place monsters from a monster group with "monsters" The actual monsters are spawned when the map is loaded. Fields: -| Field | Description -| --- | --- -| monster | (required, string) a monster group id, when the map is loaded, a random monsters from that group are spawned. -| density | (optional, float) if defined, it overrides the default monster density at the location (monster density is bigger towards the city centers) (see `map::place_spawns`). -| chance | (optional, integer or min/max array) one in x chance of spawn point being created (see `map::place_spawns`). - +| Field | Description | +| ------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| monster | (required, string) a monster group id, when the map is loaded, a random monsters from that group are spawned. | +| density | (optional, float) if defined, it overrides the default monster density at the location (monster density is bigger towards the city centers) (see `map::place_spawns`). | +| chance | (optional, integer or min/max array) one in x chance of spawn point being created (see `map::place_spawns`). | ### Place a vehicle by type or group with "vehicles" -| Field | Description -| --- | --- -| vehicle | (required, string) type of the vehicle or id of a vehicle group. -| chance | (optional, integer or min/max array) x in 100 chance of the vehicle spawning at all. The default is 1 (which means 1% probability that the vehicle spawns, you probably want something larger). -| rotation | (optional, integer) the direction the vehicle faces. -| fuel | (optional, integer) the fuel status. Default is -1 which makes the tanks 1-7% full. Positive values are interpreted as percentage of the vehicles tanks to fill (e.g. 100 means completely full). -| status | (optional, integer) default is -1 (light damage), a value of 0 means perfect condition, 1 means heavily damaged. - +| Field | Description | +| -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| vehicle | (required, string) type of the vehicle or id of a vehicle group. | +| chance | (optional, integer or min/max array) x in 100 chance of the vehicle spawning at all. The default is 1 (which means 1% probability that the vehicle spawns, you probably want something larger). | +| rotation | (optional, integer) the direction the vehicle faces. | +| fuel | (optional, integer) the fuel status. Default is -1 which makes the tanks 1-7% full. Positive values are interpreted as percentage of the vehicles tanks to fill (e.g. 100 means completely full). | +| status | (optional, integer) default is -1 (light damage), a value of 0 means perfect condition, 1 means heavily damaged. | ### Place a specific item with "item" -| Field | Description -| --- | --- -| item | (required, string) the item type id of the new item. -| chance | (optional, integer or min/max array) one in x chance that the item will spawn. Default is 1, meaning it will always spawn. -| amount | (optional, integer or min/max array) the number of items to spawn, default is 1. -| repeat | (optional, integer or min/max array) the number of times to repeat this placement, default is 1. +| Field | Description | +| ------ | -------------------------------------------------------------------------------------------------------------------------- | +| item | (required, string) the item type id of the new item. | +| chance | (optional, integer or min/max array) one in x chance that the item will spawn. Default is 1, meaning it will always spawn. | +| amount | (optional, integer or min/max array) the number of items to spawn, default is 1. | +| repeat | (optional, integer or min/max array) the number of times to repeat this placement, default is 1. | -To use this type with explicit coordinates use the name "place_item" (this if for backwards compatibility) like this: +To use this type with explicit coordinates use the name "place_item" (this if for backwards +compatibility) like this: ```json "item": { @@ -843,48 +858,45 @@ To use this type with explicit coordinates use the name "place_item" (this if fo ### Place a specific monster with "monster" -| Field | Description -| --- | --- -| monster | (required, string) type id of the monster (e.g. `mon_zombie`). -| friendly | (optional, bool) whether the monster is friendly, default is false. -| name | (optional, string) a name for that monster, optional, default is to create an unnamed monster. -| target | (optional, bool) this monster is a mission target. Only valid for `update_mapgen`. - +| Field | Description | +| -------- | ---------------------------------------------------------------------------------------------- | +| monster | (required, string) type id of the monster (e.g. `mon_zombie`). | +| friendly | (optional, bool) whether the monster is friendly, default is false. | +| name | (optional, string) a name for that monster, optional, default is to create an unnamed monster. | +| target | (optional, bool) this monster is a mission target. Only valid for `update_mapgen`. | ### Place a trap with "traps" -| Field | Description -| --- | --- -| trap | (required, string) type id of the trap (e.g. `tr_beartrap`). - +| Field | Description | +| ----- | ------------------------------------------------------------ | +| trap | (required, string) type id of the trap (e.g. `tr_beartrap`). | ### Place furniture with "furniture" -| Field | Description -| --- | --- -| furn | (required, string) type id of the furniture (e.g. `f_chair`). - +| Field | Description | +| ----- | ------------------------------------------------------------- | +| furn | (required, string) type id of the furniture (e.g. `f_chair`). | ### Place terrain with "terrain" If the terrain has the value "roof" set and is in an enclosed space, it's indoors. -| Field | Description -| --- | --- -| ter | (required, string) type id of the terrain (e.g. `t_floor`). - +| Field | Description | +| ----- | ----------------------------------------------------------- | +| ter | (required, string) type id of the terrain (e.g. `t_floor`). | ### Place rubble and smash existing terrain with "rubble" -Creates rubble and bashes existing terrain (this step is applied last, after other things like furniture/terrain have -been set). Creating rubble invokes the bashing function that can destroy terrain and cause structures to collapse. +Creates rubble and bashes existing terrain (this step is applied last, after other things like +furniture/terrain have been set). Creating rubble invokes the bashing function that can destroy +terrain and cause structures to collapse. -| Field | Description -| --- | --- -| rubble_type | (optional, furniture id, default: `f_rubble`) the type of the created rubble. -| items | (optional, bool, default: false) place items that result from bashing the structure. -| floor_type | (optional, terrain id, default: `t_dirt`) only used if there is a non-bashable wall at the location or with overwrite = true. -| overwrite | (optional, bool, default: false) if true it just writes on top of what currently exists. +| Field | Description | +| ----------- | ----------------------------------------------------------------------------------------------------------------------------- | +| rubble_type | (optional, furniture id, default: `f_rubble`) the type of the created rubble. | +| items | (optional, bool, default: false) place items that result from bashing the structure. | +| floor_type | (optional, terrain id, default: `t_dirt`) only used if there is a non-bashable wall at the location or with overwrite = true. | +| overwrite | (optional, bool, default: false) if true it just writes on top of what currently exists. | To use this type with explicit coordinates use the name "place_rubble" (no plural) like this: @@ -896,17 +908,17 @@ To use this type with explicit coordinates use the name "place_rubble" (no plura ### Place spilled liquids with "place_liquids" -Creates a liquid item at the specified location. Liquids can't currently be picked up (except for gasoline in tanks or -pumps), but can be used to add flavor to mapgen. +Creates a liquid item at the specified location. Liquids can't currently be picked up (except for +gasoline in tanks or pumps), but can be used to add flavor to mapgen. -| Field | Description -| --- | --- -| liquid | (required, item id) the item (a liquid) -| amount | (optional, integer/min-max array) amount of liquid to place (a value of 0 defaults to the item's default charges) -| chance | (optional, integer/min-max array) one in x chance of spawning a liquid, default value is 1 (100%) +| Field | Description | +| ------ | ----------------------------------------------------------------------------------------------------------------- | +| liquid | (required, item id) the item (a liquid) | +| amount | (optional, integer/min-max array) amount of liquid to place (a value of 0 defaults to the item's default charges) | +| chance | (optional, integer/min-max array) one in x chance of spawning a liquid, default value is 1 (100%) | -Example for dropping a default amount of gasoline (200 units) on the ground (either by using a character in the rows -array or explicit coordinates): +Example for dropping a default amount of gasoline (200 units) on the ground (either by using a +character in the rows array or explicit coordinates): ```json "liquids": { @@ -919,38 +931,37 @@ array or explicit coordinates): ### Place a specific item or an item from a group with "loot" -Places item(s) from an item group, or an individual item. An important distinction between this and `place_item` and -`item`/`items` is that `loot` can spawn a single item from a distribution group (without looping). It can also spawn a -matching magazine and ammo for guns. +Places item(s) from an item group, or an individual item. An important distinction between this and +`place_item` and `item`/`items` is that `loot` can spawn a single item from a distribution group +(without looping). It can also spawn a matching magazine and ammo for guns. **Note**: Either `group` or `item` must be specified, but not both. -| Field | Description -| --- | --- -| group | (string) the item group to use (see `ITEM_SPAWN.md` for notes on collection vs distribution groups) -| item | (string) the type id of the item to spawn -| chance | (optional, integer) x in 100 chance of item(s) spawning. Defaults to 100. -| ammo | (optional, integer) x in 100 chance of item(s) spawning with the default amount of ammo. Defaults to 0. -| magazine | (optional, integer) x in 100 chance of item(s) spawning with the default magazine. Defaults to 0. - +| Field | Description | +| -------- | ------------------------------------------------------------------------------------------------------- | +| group | (string) the item group to use (see `ITEM_SPAWN.md` for notes on collection vs distribution groups) | +| item | (string) the type id of the item to spawn | +| chance | (optional, integer) x in 100 chance of item(s) spawning. Defaults to 100. | +| ammo | (optional, integer) x in 100 chance of item(s) spawning with the default amount of ammo. Defaults to 0. | +| magazine | (optional, integer) x in 100 chance of item(s) spawning with the default magazine. Defaults to 0. | ### Plant seeds in a planter with "sealed_item" Places an item or item group inside furniture that has special handling for items. -This is intended for furniture such as `f_plant_harvest` with the `PLANT` flag, because placing items on such furniture -via the other means will not work (since they have the `NOITEM` FLAG). +This is intended for furniture such as `f_plant_harvest` with the `PLANT` flag, because placing +items on such furniture via the other means will not work (since they have the `NOITEM` FLAG). -On such furniture, there is supposed to be a single (hidden) seed item which dictates the species of plant. Using -`sealed_item`, you can create such plants by specifying the furniture and a seed item. +On such furniture, there is supposed to be a single (hidden) seed item which dictates the species of +plant. Using `sealed_item`, you can create such plants by specifying the furniture and a seed item. **Note**: Exactly one of "item" or "items" must be given (but not both). -| Field | Description -| --- | --- -| furniture | (string) the id of the chosen furniture. -| item | spawn an item as the "item" special -| items | spawn an item group as the "items" special. +| Field | Description | +| --------- | ------------------------------------------- | +| furniture | (string) the id of the chosen furniture. | +| item | spawn an item as the "item" special | +| items | spawn an item group as the "items" special. | Example: @@ -963,28 +974,26 @@ Example: }, ``` - ### Place messages with "graffiti" -Places a graffiti message at the location. Either "text" or "snippet" must be defined. The message may include tags like -``, ``, and `` that will insert a randomly generated name, or `` that will -insert the nearest city name. - -| Field | Description -| --- | --- -| text | (optional, string) the message that will be placed. -| snippet | (optional, string) a category of snippets that the message will be pulled from. +Places a graffiti message at the location. Either "text" or "snippet" must be defined. The message +may include tags like ``, ``, and `` that will insert a randomly +generated name, or `` that will insert the nearest city name. +| Field | Description | +| ------- | ------------------------------------------------------------------------------- | +| text | (optional, string) the message that will be placed. | +| snippet | (optional, string) a category of snippets that the message will be pulled from. | ### Place a zone for an NPC faction with "zones" NPCs in the faction will use the zone to influence the AI. -| Field | Description -| --- | --- -| type | (required, string) Values: `"NPC_RETREAT"`, `"NPC_NO_INVESTIGATE"`, or `"NPC_INVESTIGATE_ONLY"`. -| faction | (required, string) the faction id of the NPC faction that will use the zone. -| name | (optional, string) the name of the zone. +| Field | Description | +| ------- | ------------------------------------------------------------------------------------------------ | +| type | (required, string) Values: `"NPC_RETREAT"`, `"NPC_NO_INVESTIGATE"`, or `"NPC_INVESTIGATE_ONLY"`. | +| faction | (required, string) the faction id of the NPC faction that will use the zone. | +| name | (optional, string) the name of the zone. | The `type` field values affect NPC behavior. NPCs will: @@ -992,89 +1001,88 @@ The `type` field values affect NPC behavior. NPCs will: - Not move to the see the source of unseen sounds coming from `NPC_NO_INVESTIGATE` zones. - Not move to the see the source of unseen sounds coming from outside `NPC_INVESTIGATE_ONLY` zones. - ### Translate terrain type with "translate_ter" -Translates one type of terrain into another type of terrain. There is no reason to do this with normal mapgen, but it -is useful for setting a baseline with `update_mapgen`. - -| Field | Description -| --- | --- -| from | (required, string) the terrain id of the terrain to be transformed -| to | (required, string) the terrain id that the from terrain will transformed into +Translates one type of terrain into another type of terrain. There is no reason to do this with +normal mapgen, but it is useful for setting a baseline with `update_mapgen`. +| Field | Description | +| ----- | ----------------------------------------------------------------------------- | +| from | (required, string) the terrain id of the terrain to be transformed | +| to | (required, string) the terrain id that the from terrain will transformed into | ### Apply mapgen transformation with "ter_furn_transforms" -Run a `ter_furn_transform` at the specified location. This is mostly useful for applying transformations as part of -an `update_mapgen`, as normal mapgen can just specify the terrain directly. +Run a `ter_furn_transform` at the specified location. This is mostly useful for applying +transformations as part of an `update_mapgen`, as normal mapgen can just specify the terrain +directly. - "transform": (required, string) the id of the `ter_furn_transform` to run. - ## Rotate the map with "rotation" -Rotates the generated map after all the other mapgen stuff has been done. The value can be a single integer or a range -(out of which a value will be randomly chosen). Example: `"rotation": [ 0, 3 ]` +Rotates the generated map after all the other mapgen stuff has been done. The value can be a single +integer or a range (out of which a value will be randomly chosen). Example: `"rotation": [ 0, 3 ]` Values are 90° steps. - ## Pre-load a base mapgen with "predecessor_mapgen" -Specifying an overmap terrain id here will run the entire mapgen for that overmap terrain type first, before applying -the rest of the mapgen defined here. The primary use case for this is when our mapgen for a location takes place in a -natural feature like a forest, swamp, or lake shore. Many existing JSON mapgen attempt to emulate the mapgen of the type -they're being placed on (e.g. a cabin in the forest has placed the trees, grass and clutter of a forest to try to make -the cabin fit in) which leads to them being out of sync when the generation of that type changes. By specifying the -`predecessor_mapgen`, you can instead focus on the things that are added to the existing location type. +Specifying an overmap terrain id here will run the entire mapgen for that overmap terrain type +first, before applying the rest of the mapgen defined here. The primary use case for this is when +our mapgen for a location takes place in a natural feature like a forest, swamp, or lake shore. Many +existing JSON mapgen attempt to emulate the mapgen of the type they're being placed on (e.g. a cabin +in the forest has placed the trees, grass and clutter of a forest to try to make the cabin fit in) +which leads to them being out of sync when the generation of that type changes. By specifying the +`predecessor_mapgen`, you can instead focus on the things that are added to the existing location +type. Example: `"predecessor_mapgen": "forest"` - # Using update_mapgen -**update_mapgen** is a variant of normal JSON mapgen. Instead of creating a new overmap tile, it -updates an existing overmap tile with a specific set of changes. Currently, it only works within -the NPC mission interface, but it will be expanded to be a general purpose tool for modifying -existing maps. +**update_mapgen** is a variant of normal JSON mapgen. Instead of creating a new overmap tile, it +updates an existing overmap tile with a specific set of changes. Currently, it only works within the +NPC mission interface, but it will be expanded to be a general purpose tool for modifying existing +maps. -update_mapgen generally uses the same fields as JSON mapgen, with a few exceptions. update_mapgen has a few new fields -to support missions, as well as ways to specify which overmap tile will be updated. +update_mapgen generally uses the same fields as JSON mapgen, with a few exceptions. update_mapgen +has a few new fields to support missions, as well as ways to specify which overmap tile will be +updated. ## Overmap tile specification -update_mapgen updates an existing overmap tile. These fields provide a way to specify which tile to update. +update_mapgen updates an existing overmap tile. These fields provide a way to specify which tile to +update. ### "assign_mission_target" -assign_mission_target assigns an overmap tile as the target of a mission. Any update_mapgen in the same scope will -update that overmap tile. The closet overmap terrain with the required terrain ID will be used, and if there is no -matching terrain, an overmap special of om_special type will be created and then the om_terrain within that special will -be used. - -| Field | Description -| --- | --- -| om_terrain | (required, string) the overmap terrain ID of the mission target -| om_special | (required, string) the overmap special ID of the mission target +assign_mission_target assigns an overmap tile as the target of a mission. Any update_mapgen in the +same scope will update that overmap tile. The closet overmap terrain with the required terrain ID +will be used, and if there is no matching terrain, an overmap special of om_special type will be +created and then the om_terrain within that special will be used. +| Field | Description | +| ---------- | --------------------------------------------------------------- | +| om_terrain | (required, string) the overmap terrain ID of the mission target | +| om_special | (required, string) the overmap special ID of the mission target | ### "om_terrain" -The closest overmap tile of type om_terrain in the closest overmap special of type om_special will be used. The overmap -tile will be updated but will not be set as the mission target. +The closest overmap tile of type om_terrain in the closest overmap special of type om_special will +be used. The overmap tile will be updated but will not be set as the mission target. -| Field | Description -| --- | --- -| om_terrain | (required, string) the overmap terrain ID of the mission target -| om_special | (required, string) the overmap special ID of the mission target +| Field | Description | +| ---------- | --------------------------------------------------------------- | +| om_terrain | (required, string) the overmap terrain ID of the mission target | +| om_special | (required, string) the overmap special ID of the mission target | # Mission specials + update_mapgen adds new optional keywords to a few mapgen JSON items. ### "target" -place_npc, place_monster, and place_computer can take an optional target boolean. If they have `"target": true` and are -invoked by update_mapgen with a valid mission, then the NPC, monster, or computer will be marked as the target of the -mission. - +place_npc, place_monster, and place_computer can take an optional target boolean. If they have +`"target": true` and are invoked by update_mapgen with a valid mission, then the NPC, monster, or +computer will be marked as the target of the mission. diff --git a/doc/MARTIALART_JSON.md b/doc/MARTIALART_JSON.md index 6d9e6ef9e642..3fa4105a1260 100644 --- a/doc/MARTIALART_JSON.md +++ b/doc/MARTIALART_JSON.md @@ -103,30 +103,36 @@ The bonuses arrays contain any number of bonus entries like this: } ``` -"stat": affected statistic, any of: "hit", "dodge", "block", "speed", "movecost", "damage", "armor", "arpen", -"type": damage type for the affected statistic ("bash", "cut", "heat", etc.), only needed if the affected statistic is "damage", "armor", or "arpen". -"scale": the value of the bonus itself. -"scaling-stat": scaling stat, any of: "str", "dex", "int", "per". Optional. If the scaling stat is specified, the value of the bonus is multiplied by the corresponding user stat. +"stat": affected statistic, any of: "hit", "dodge", "block", "speed", "movecost", "damage", "armor", +"arpen", "type": damage type for the affected statistic ("bash", "cut", "heat", etc.), only needed +if the affected statistic is "damage", "armor", or "arpen". "scale": the value of the bonus itself. +"scaling-stat": scaling stat, any of: "str", "dex", "int", "per". Optional. If the scaling stat is +specified, the value of the bonus is multiplied by the corresponding user stat. Bonuses must be written in the correct order. -Tokens of `useless` type will not cause an error, but will not have any effect. -For example, `speed` in a technique will have no effect (`movecost` should be used for techniques). +Tokens of `useless` type will not cause an error, but will not have any effect. For example, `speed` +in a technique will have no effect (`movecost` should be used for techniques). Currently extra elemental damage is not applied, but extra elemental armor is (after regular armor). -Examples: -Incoming bashing damage is decreased by 30% of strength value. Only useful on buffs: -* `flat_bonuses : [ { "stat": "armor", "type": "bash", "scaling-stat": "str", "scale": 0.3 } ]` +Examples: Incoming bashing damage is decreased by 30% of strength value. Only useful on buffs: + +- `flat_bonuses : [ { "stat": "armor", "type": "bash", "scaling-stat": "str", "scale": 0.3 } ]` All cutting damage dealt is multiplied by `(10% of dexterity)*(damage)`: -* `mult_bonuses : [ { "stat": "damage", "type": "cut", "scaling-stat": "dex", "scale": 0.1 } ]` + +- `mult_bonuses : [ { "stat": "damage", "type": "cut", "scaling-stat": "dex", "scale": 0.1 } ]` Move cost is decreased by 100% of strength value -* `flat_bonuses : [ { "stat": "movecost", "scaling-stat": "str", "scale": -1.0 } ]` + +- `flat_bonuses : [ { "stat": "movecost", "scaling-stat": "str", "scale": -1.0 } ]` ### Place relevant items in the world and chargen -Starting trait selection of your martial art goes in mutations.json. Place your art in the right category (self-defense, Shaolin animal form, melee style, etc) +Starting trait selection of your martial art goes in mutations.json. Place your art in the right +category (self-defense, Shaolin animal form, melee style, etc) -Use json/itemgroups/ to place your martial art book and any martial weapons you've made for the art into spawns in various locations in the world. If you don't place your weapons in there, only recipes to craft them will be an option. +Use json/itemgroups/ to place your martial art book and any martial weapons you've made for the art +into spawns in various locations in the world. If you don't place your weapons in there, only +recipes to craft them will be an option. diff --git a/doc/MISSIONS_JSON.md b/doc/MISSIONS_JSON.md index f35569888800..4bbfc8a7f6a1 100644 --- a/doc/MISSIONS_JSON.md +++ b/doc/MISSIONS_JSON.md @@ -1,162 +1,181 @@ # Creating missions -NPCs can assign missions to the player. There is a fairly regular structure for this: +NPCs can assign missions to the player. There is a fairly regular structure for this: ```JSON - { - "id": "MISSION_GET_BLACK_BOX_TRANSCRIPT", - "type": "mission_definition", - "name": "Retrieve Black Box Transcript", - "description": "Decrypt the contents of the black box using a terminal from a nearby lab.", - "goal": "MGOAL_FIND_ITEM", - "difficulty": 2, - "value": 150000, - "item": "black_box_transcript", - "start": { - "effect": { "u_buy_item": "black_box" }, - "assign_mission_target": { "om_terrain": "lab", "reveal_radius": 3 } - }, - "origins": [ "ORIGIN_SECONDARY" ], - "followup": "MISSION_EXPLORE_SARCOPHAGUS", - "dialogue": { - "describe": "With the black box in hand, we need to find a lab.", - "offer": "Thanks to your searching we've got the black box but now we need to have a look'n-side her. Now, most buildings don't have power anymore but there are a few that might be of use. Have you ever seen one of those science labs that have popped up in the middle of nowhere? Them suckers have a glowing terminal out front so I know they have power somewhere inside'em. If you can get inside and find a computer lab that still works you ought to be able to find out what's in the black box.", - "accepted": "Fuck ya, America!", - "rejected": "Do you have any better ideas?", - "advice": "When I was play'n with the terminal for the one I ran into it kept asking for an ID card. Finding one would be the first order of business.", - "inquire": "How 'bout that black box?", - "success": "America, fuck ya! I was in the guard a few years back so I'm confident I can make heads-or-tails of these transmissions.", - "success_lie": "What?! I out'ta whip you're ass.", - "failure": "Damn, I maybe we can find an egg-head to crack the terminal." - } +{ + "id": "MISSION_GET_BLACK_BOX_TRANSCRIPT", + "type": "mission_definition", + "name": "Retrieve Black Box Transcript", + "description": "Decrypt the contents of the black box using a terminal from a nearby lab.", + "goal": "MGOAL_FIND_ITEM", + "difficulty": 2, + "value": 150000, + "item": "black_box_transcript", + "start": { + "effect": { "u_buy_item": "black_box" }, + "assign_mission_target": { "om_terrain": "lab", "reveal_radius": 3 } + }, + "origins": ["ORIGIN_SECONDARY"], + "followup": "MISSION_EXPLORE_SARCOPHAGUS", + "dialogue": { + "describe": "With the black box in hand, we need to find a lab.", + "offer": "Thanks to your searching we've got the black box but now we need to have a look'n-side her. Now, most buildings don't have power anymore but there are a few that might be of use. Have you ever seen one of those science labs that have popped up in the middle of nowhere? Them suckers have a glowing terminal out front so I know they have power somewhere inside'em. If you can get inside and find a computer lab that still works you ought to be able to find out what's in the black box.", + "accepted": "Fuck ya, America!", + "rejected": "Do you have any better ideas?", + "advice": "When I was play'n with the terminal for the one I ran into it kept asking for an ID card. Finding one would be the first order of business.", + "inquire": "How 'bout that black box?", + "success": "America, fuck ya! I was in the guard a few years back so I'm confident I can make heads-or-tails of these transmissions.", + "success_lie": "What?! I out'ta whip you're ass.", + "failure": "Damn, I maybe we can find an egg-head to crack the terminal." } +} ``` ### type + Must always be there and must always be "mission_definition". ### id -The mission id is required, but for new missions, it can be arbitrary. Convention is to start -it with "MISSION" and to use a fairly descriptive name. + +The mission id is required, but for new missions, it can be arbitrary. Convention is to start it +with "MISSION" and to use a fairly descriptive name. ### name + The name is also required, and is displayed to the user in the 'm'issions menu. ### description + Not required, but it's strongly recommended that you summarize all relevant info for the mission. -You may refer to mission end effects of the "u_buy_item" type, as long as they do not come at a -cost to the player. See the example below: +You may refer to mission end effects of the "u_buy_item" type, as long as they do not come at a cost +to the player. See the example below: + ```JSON - "id": "MISSION_EXAMPLE_TOKENS", - "type": "mission_definition", - "name": "Murder Money", - "description": "Whack the target in exchange for c-notes and cigarettes.", - "goal": "MGOAL_ASSASSINATE", - "end": { - "effect": [ - { "u_buy_item": "FMCNote", "count": 999 }, - { "u_buy_item": "cig", "count": 666 } ] - } +"id": "MISSION_EXAMPLE_TOKENS", +"type": "mission_definition", +"name": "Murder Money", +"description": "Whack the target in exchange for c-notes and cigarettes.", +"goal": "MGOAL_ASSASSINATE", +"end": { + "effect": [ + { "u_buy_item": "FMCNote", "count": 999 }, + { "u_buy_item": "cig", "count": 666 } ] +} ``` -This system may be expanded in the future to allow referring to other mission parameters and effects. + +This system may be expanded in the future to allow referring to other mission parameters and +effects. ### goal + Must be included, and must be one of these strings: -goal string | Goal conditions ---- | --- -`MGOAL_GO_TO` | Reach a specific overmap tile -`MGOAL_GO_TO_TYPE` | Reach any instance of a specified overmap tile type -`MGOAL_COMPUTER_TOGGLE` | Activating the correct terminal will complete the mission -`MGOAL_FIND_ITEM` | Find 1 or more items of a given type -`MGOAL_FIND_ITEM_GROUP` | Find 1 or more items of a given item_group. -`MGOAL_FIND_ANY_ITEM` | Find 1 or more items of a given type, tagged for this mission -`MGOAL_FIND_MONSTER` | Find and retrieve a friendly monster -`MGOAL_FIND_NPC` | Find a specific NPC -`MGOAL_TALK_TO_NPC` | Talk to a specific NPC -`MGOAL_RECRUIT_NPC` | Recruit a specific NPC -`MGOAL_RECRUIT_NPC_CLASS` | Recruit an NPC of a specific class -`MGOAL_ASSASSINATE` | Kill a specific NPC -`MGOAL_KILL_MONSTER` | Kill a specific hostile monster -`MGOAL_KILL_MONSTER_TYPE` | Kill some number of a specific monster type -`MGOAL_KILL_MONSTER_SPEC` | Kill some number of monsters from a specific species -`MGOAL_CONDITION` | Satisfy the dynamically created condition and talk to the mission giver +| goal string | Goal conditions | +| ------------------------- | ----------------------------------------------------------------------- | +| `MGOAL_GO_TO` | Reach a specific overmap tile | +| `MGOAL_GO_TO_TYPE` | Reach any instance of a specified overmap tile type | +| `MGOAL_COMPUTER_TOGGLE` | Activating the correct terminal will complete the mission | +| `MGOAL_FIND_ITEM` | Find 1 or more items of a given type | +| `MGOAL_FIND_ITEM_GROUP` | Find 1 or more items of a given item_group. | +| `MGOAL_FIND_ANY_ITEM` | Find 1 or more items of a given type, tagged for this mission | +| `MGOAL_FIND_MONSTER` | Find and retrieve a friendly monster | +| `MGOAL_FIND_NPC` | Find a specific NPC | +| `MGOAL_TALK_TO_NPC` | Talk to a specific NPC | +| `MGOAL_RECRUIT_NPC` | Recruit a specific NPC | +| `MGOAL_RECRUIT_NPC_CLASS` | Recruit an NPC of a specific class | +| `MGOAL_ASSASSINATE` | Kill a specific NPC | +| `MGOAL_KILL_MONSTER` | Kill a specific hostile monster | +| `MGOAL_KILL_MONSTER_TYPE` | Kill some number of a specific monster type | +| `MGOAL_KILL_MONSTER_SPEC` | Kill some number of monsters from a specific species | +| `MGOAL_CONDITION` | Satisfy the dynamically created condition and talk to the mission giver | ### monster_species + For "MGOAL_KILL_MONSTER_SPEC", sets the target monster species. ### monster_type + For "MGOAL_KILL_MONSTER_TYPE", sets the target monster type. ### monster_kill_goal -For "MGOAL_KILL_MONSTER_SPEC" and "MGOAL_KILL_MONSTER_TYPE", sets the number of monsters above -the player's current kill count that must be killed to complete the mission. + +For "MGOAL_KILL_MONSTER_SPEC" and "MGOAL_KILL_MONSTER_TYPE", sets the number of monsters above the +player's current kill count that must be killed to complete the mission. ### goal_condition -For "MGOAL_CONDITION", defines the condition that must be satisified for the mission to be considered complete. -Conditions are explained in more detail in [NPCs.md](./NPCs.md), and are used here in exactly the same way. + +For "MGOAL_CONDITION", defines the condition that must be satisified for the mission to be +considered complete. Conditions are explained in more detail in [NPCs.md](./NPCs.md), and are used +here in exactly the same way. ### dialogue -This is a dictionary of strings. The NPC says these exact strings in response to the player -inquiring about the mission or reporting its completion. All these strings are required, even if they may not be used in the mission. - -string ID | Usage ---- | --- -`describe` | The NPC's overall description of the mission -`offer` | The specifics of the mission given when the player selects that mission for consideration -`accepted` | The NPC's response if the player accepts the mission -`rejected` | The NPC's response if the player refuses the mission -`advice` | If the player asks for advice on how to complete the mission, they hear this -`inquire` | This is used if the NPC asks the player how the mission is going -`success` | The NPC's response to a report that the mission was successful -`success_lie` | The NPC's response if they catch the player lying about a mission's success -`failure` | The NPC's response if the player reports a failed mission + +This is a dictionary of strings. The NPC says these exact strings in response to the player +inquiring about the mission or reporting its completion. All these strings are required, even if +they may not be used in the mission. + +| string ID | Usage | +| ------------- | ----------------------------------------------------------------------------------------- | +| `describe` | The NPC's overall description of the mission | +| `offer` | The specifics of the mission given when the player selects that mission for consideration | +| `accepted` | The NPC's response if the player accepts the mission | +| `rejected` | The NPC's response if the player refuses the mission | +| `advice` | If the player asks for advice on how to complete the mission, they hear this | +| `inquire` | This is used if the NPC asks the player how the mission is going | +| `success` | The NPC's response to a report that the mission was successful | +| `success_lie` | The NPC's response if they catch the player lying about a mission's success | +| `failure` | The NPC's response if the player reports a failed mission | ### start -Optional field. If it is present and a string, it must be name of a function in mission_start:: -that takes a mission * and performs the start code for the mission. This allows missions other -than the standard mission types to be run. A hardcoded function is currently necessary to set -up missions with "MGOAL_COMPUTER_TOGGLE". + +Optional field. If it is present and a string, it must be name of a function in mission_start:: that +takes a mission * and performs the start code for the mission. This allows missions other than the +standard mission types to be run. A hardcoded function is currently necessary to set up missions +with "MGOAL_COMPUTER_TOGGLE". Alternately, if present, it can be an object as described below. ### start / end / fail effects + If any of these optional fields are present they can be objects with the following fields contained: #### effect -This is an effects array, exactly as defined in [NPCs.md](./NPCs.md), and can use any of the values from -effects. In all cases, the NPC involved is the quest giver. + +This is an effects array, exactly as defined in [NPCs.md](./NPCs.md), and can use any of the values +from effects. In all cases, the NPC involved is the quest giver. #### reveal_om_ter -This can be a string or a list of strings, all of which must be overmap terrain ids. A randomly -selected overmap terrain tile with that id - or one of the ids from list, randomly selected - -will be revealed, and there is a 1 in 3 chance that the road route to the map tile will also -be revealed. + +This can be a string or a list of strings, all of which must be overmap terrain ids. A randomly +selected overmap terrain tile with that id - or one of the ids from list, randomly selected - will +be revealed, and there is a 1 in 3 chance that the road route to the map tile will also be revealed. #### assign_mission_target -The `assign_mission_target` object specifies the criteria for finding (or creating if -necessary) a particular overmap terrain and designating it as the mission target. Its parameters -allow control over how it is picked and how some effects (such as revealing the surrounding area) -are applied afterwards. The `om_terrain` is the only required field. - - Identifier | Description ---- | --- -`om_terrain` | ID of overmap terrain which will be selected as the target. Mandatory. -`om_terrain_match_type`| Matching rule to use with `om_terrain`. Defaults to TYPE. Details below. -`om_special` | ID of overmap special containing the overmap terrain. -`om_terrain_replace` | ID of overmap terrain to be found and replaced if `om_terrain` cannot be found. -`reveal_radius` | Radius in overmap terrain coordinates to reveal. -`must_see` | If true, the `om_terrain` must have been seen already. -`cant_see` | If true, the `om_terrain` must not have been seen already. -`random` | If true, a random matching `om_terrain` is used. If false, the closest is used. -`search_range` | Range in overmap terrain coordinates to look for a matching `om_terrain`. -`min_distance` | Range in overmap terrain coordinates. Instances of `om_terrain` in this range will be ignored. -`origin_npc` | Start the search at the NPC's, rather than the player's, current position. -`z` | If specified, will be used rather than the player or NPC's z when searching. -`offset_x`,`offset_y`,`offset_z` | After finding or creating `om_terrain`, offset the mission target terrain by the offsets in overmap terrain coordinates. +The `assign_mission_target` object specifies the criteria for finding (or creating if necessary) a +particular overmap terrain and designating it as the mission target. Its parameters allow control +over how it is picked and how some effects (such as revealing the surrounding area) are applied +afterwards. The `om_terrain` is the only required field. + +| Identifier | Description | +| ------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------ | +| `om_terrain` | ID of overmap terrain which will be selected as the target. Mandatory. | +| `om_terrain_match_type` | Matching rule to use with `om_terrain`. Defaults to TYPE. Details below. | +| `om_special` | ID of overmap special containing the overmap terrain. | +| `om_terrain_replace` | ID of overmap terrain to be found and replaced if `om_terrain` cannot be found. | +| `reveal_radius` | Radius in overmap terrain coordinates to reveal. | +| `must_see` | If true, the `om_terrain` must have been seen already. | +| `cant_see` | If true, the `om_terrain` must not have been seen already. | +| `random` | If true, a random matching `om_terrain` is used. If false, the closest is used. | +| `search_range` | Range in overmap terrain coordinates to look for a matching `om_terrain`. | +| `min_distance` | Range in overmap terrain coordinates. Instances of `om_terrain` in this range will be ignored. | +| `origin_npc` | Start the search at the NPC's, rather than the player's, current position. | +| `z` | If specified, will be used rather than the player or NPC's z when searching. | +| `offset_x`,`offset_y`,`offset_z` | After finding or creating `om_terrain`, offset the mission target terrain by the offsets in overmap terrain coordinates. | **example** + ```JSON { "assign_mission_target": { @@ -171,65 +190,71 @@ are applied afterwards. The `om_terrain` is the only required field. } ``` -If the `om_terrain` is part of an overmap special, it's essential to specify the `om_special` -value as well--otherwise, the game will not know how to spawn the entire special. +If the `om_terrain` is part of an overmap special, it's essential to specify the `om_special` value +as well--otherwise, the game will not know how to spawn the entire special. `om_terrain_match_type` defaults to TYPE if unspecified, and has the following possible values: -* `EXACT` - The provided string must completely match the overmap terrain id, - including linear direction suffixes for linear terrain types or rotation - suffixes for rotated terrain types. +- `EXACT` - The provided string must completely match the overmap terrain id, including linear + direction suffixes for linear terrain types or rotation suffixes for rotated terrain types. -* `TYPE` - The provided string must completely match the base type id of the - overmap terrain id, which means that suffixes for rotation and linear terrain - types are ignored. +- `TYPE` - The provided string must completely match the base type id of the overmap terrain id, + which means that suffixes for rotation and linear terrain types are ignored. -* `PREFIX` - The provided string must be a complete prefix (with additional - parts delimited by an underscore) of the overmap terrain id. For example, - "forest" will match "forest" or "forest_thick" but not "forestcabin". +- `PREFIX` - The provided string must be a complete prefix (with additional parts delimited by an + underscore) of the overmap terrain id. For example, "forest" will match "forest" or "forest_thick" + but not "forestcabin". -* `CONTAINS` - The provided string must be contained within the overmap terrain - id, but may occur at the beginning, end, or middle and does not have any rules - about underscore delimiting. +- `CONTAINS` - The provided string must be contained within the overmap terrain id, but may occur at + the beginning, end, or middle and does not have any rules about underscore delimiting. -If an `om_special` must be placed, it will follow the same placement rules as defined in its -overmap special definition, respecting allowed terrains, distance from cities, road connections, -and so on. Consequently, the more restrictive the rules, the less likely this placement will -succeed (as it is competing for space with already-spawned specials). +If an `om_special` must be placed, it will follow the same placement rules as defined in its overmap +special definition, respecting allowed terrains, distance from cities, road connections, and so on. +Consequently, the more restrictive the rules, the less likely this placement will succeed (as it is +competing for space with already-spawned specials). -`om_terrain_replace` is only relevent if the `om_terrain` is not part of an overmap special. -This value is used if the `om_terrain` cannot be found, and will be used as an alternative target -which will then be replaced with the `om_terrain` value. +`om_terrain_replace` is only relevent if the `om_terrain` is not part of an overmap special. This +value is used if the `om_terrain` cannot be found, and will be used as an alternative target which +will then be replaced with the `om_terrain` value. -If `must_see` is set to true, the game will not create the terrain if it can't be found. It tries -to avoid having new terrains magically appear in areas where the player has already been, and this -is a consequence. +If `must_see` is set to true, the game will not create the terrain if it can't be found. It tries to +avoid having new terrains magically appear in areas where the player has already been, and this is a +consequence. `reveal_radius`, `min_distance`, and `search_range` are all in overmap terrain coordinates (an -overmap is currently 180 x 180 OMT units). The search is centered on the player unless -`origin_npc` is set, in which case it centered on the NPC. Currently, there is rarely a -difference between the two, but it is possible to assign missions over a radio. The search gives -preference to existing overmaps (and will only spawn new overmaps if the terrain can't be found -on existing overmaps), and only executes on the player's current z-level. The `z` attribute can -be used to override this and search on a different z-level than the player--this is an absolute -value rather than relative. +overmap is currently 180 x 180 OMT units). The search is centered on the player unless `origin_npc` +is set, in which case it centered on the NPC. Currently, there is rarely a difference between the +two, but it is possible to assign missions over a radio. The search gives preference to existing +overmaps (and will only spawn new overmaps if the terrain can't be found on existing overmaps), and +only executes on the player's current z-level. The `z` attribute can be used to override this and +search on a different z-level than the player--this is an absolute value rather than relative. `offset_x`, `offset_y`, and `offset_z` change the final location of the mission target by their -values. This can change the mission target's overmap terrain type away from `om_terrain`. +values. This can change the mission target's overmap terrain type away from `om_terrain`. #### update_mapgen -The `update_mapgen` object or array provides a way to modify existing overmap tiles (including the ones created by "assign_mission_target") to add mission specific monsters, NPCs, computers, or items. + +The `update_mapgen` object or array provides a way to modify existing overmap tiles (including the +ones created by "assign_mission_target") to add mission specific monsters, NPCs, computers, or +items. As an array, `update_mapgen` consists of two or more `update_mapgen` objects. -As an object, `update_mapgen` contains any valid JSON mapgen objects. The objects are placed on the mission target terrain from "assign_mission_target" or optionally the closest overmap terrain specified by the `om_terrain` and `om_special` fields. If "mapgen_update_id" is specified, the "mapge_update" object with the matching "mapgen_update_id" will be executed. +As an object, `update_mapgen` contains any valid JSON mapgen objects. The objects are placed on the +mission target terrain from "assign_mission_target" or optionally the closest overmap terrain +specified by the `om_terrain` and `om_special` fields. If "mapgen_update_id" is specified, the +"mapge_update" object with the matching "mapgen_update_id" will be executed. See doc/MAPGEN.md for more details on JSON mapgen and `update_mapgen`. -An NPC, monster, or computer placed using `update_mapgen` will be the target of a mission if it has the `target` boolean set to `true` in its `place` object in `update_mapgen`. +An NPC, monster, or computer placed using `update_mapgen` will be the target of a mission if it has +the `target` boolean set to `true` in its `place` object in `update_mapgen`. ## Adding new missions to NPC dialogue -In order to assign missions to NPCs, the first step is to find that NPC's definition. For unique NPCs this is usually at the top of the npc's JSON file and looks something like this: + +In order to assign missions to NPCs, the first step is to find that NPC's definition. For unique +NPCs this is usually at the top of the npc's JSON file and looks something like this: + ```JSON { "type": "npc", @@ -245,23 +270,26 @@ In order to assign missions to NPCs, the first step is to find that NPC's defini "faction": "lobby_beggars" }, ``` + Add a new line that defines the NPC's starting mission, eg: + ``` "mission_offered": "MISSION_BEGGAR_2_BOX_SMALL" ``` -Any NPC that has missions needs to have a dialogue option that leads to TALK_MISSION_LIST, to get the player -started on their first mission for the NPC, and either: +Any NPC that has missions needs to have a dialogue option that leads to TALK_MISSION_LIST, to get +the player started on their first mission for the NPC, and either: -* Add one of their talk_topic IDs to the list of generic mission reponse IDs in the first -talk_topic of data/json/npcs/TALK_COMMON_MISSION.json, or -* Have a similar talk_topic with responses that lead to TALK_MISSION_INQUIRE and -TALK_MISSION_LIST_ASSIGNED. +- Add one of their talk_topic IDs to the list of generic mission reponse IDs in the first talk_topic + of data/json/npcs/TALK_COMMON_MISSION.json, or +- Have a similar talk_topic with responses that lead to TALK_MISSION_INQUIRE and + TALK_MISSION_LIST_ASSIGNED. Either of these options will allow the player to do normal mission management dialogue with the NPC. -This is an example of how a custom mission inquiry might appear. This will only appear in the NPC's dialogue -options if the player has already been assigned a mission. +This is an example of how a custom mission inquiry might appear. This will only appear in the NPC's +dialogue options if the player has already been assigned a mission. + ```JSON { "type": "talk_topic", diff --git a/doc/MODDING.md b/doc/MODDING.md index e1c7c86c2ed6..8fc2f5ea7137 100644 --- a/doc/MODDING.md +++ b/doc/MODDING.md @@ -1,59 +1,97 @@ # Modding guide -Certain features of the game can be modified without rebuilding the game from source code. This includes professions, monsters, npcs, and more. Just modify the pertinent files and run the game to see your changes. +Certain features of the game can be modified without rebuilding the game from source code. This +includes professions, monsters, npcs, and more. Just modify the pertinent files and run the game to +see your changes. -The majority of modding is done by editing JSON files. An in-depth review of all json files and their appropriate fields is available in [JSON_INFO.md](JSON_INFO.md). +The majority of modding is done by editing JSON files. An in-depth review of all json files and +their appropriate fields is available in [JSON_INFO.md](JSON_INFO.md). ## The basics ### Creating a barebones mod -A mod is created by creating a folder within Cataclysm's `data/mods` directory. The mod's properties are set by the `modinfo.json` file that is present within that folder. In order for Cataclysm to recognize the folder as a mod, it **must** have a `modinfo.json` file present within it. + +A mod is created by creating a folder within Cataclysm's `data/mods` directory. The mod's properties +are set by the `modinfo.json` file that is present within that folder. In order for Cataclysm to +recognize the folder as a mod, it **must** have a `modinfo.json` file present within it. + + ### Modinfo.json -The modinfo.json file is a file that contains metadata for your mod. Every mod must have a `modinfo.json` file in order for Cataclysm to find it. -A barebones `modinfo.json` file looks like this: -````json + +The modinfo.json file is a file that contains metadata for your mod. Every mod must have a +`modinfo.json` file in order for Cataclysm to find it. A barebones `modinfo.json` file looks like +this: + +```json [ { "type": "MOD_INFO", "id": "Mod_ID", "name": "Mod's Display Name", - "authors": [ "Your name here", "Your friend's name if you want" ], + "authors": ["Your name here", "Your friend's name if you want"], "description": "Your description here", "category": "content", - "dependencies": [ "bn" ] + "dependencies": ["bn"] } ] -```` -The `category` attribute denotes where the mod will appear in the mod selection menu. These are the available categories to choose from, with some examples chosen from mods that existed when this document was written. Pick whichever one applies best to your mod when writing your modinfo file. - - `content` - A mod that adds a lot of stuff. Typically reserved for very large mods or complete game overhauls (eg: Core game files, Aftershock) - - `items` - A mod that adds new items and recipes to the game (eg: More survival tools) - - `creatures` - A mod that adds new creatures or NPCs to the game (eg: Modular turrets) - - `misc_additions` - Miscellaneous content additions to the game (eg: Alternative map key, Crazy cataclysm) - - `buildings` - New overmap locations and structures (eg: Fuji's more buildings). If you're blacklisting buildings from spawning, this is also a usable category (eg: No rail stations). - - `vehicles` - New cars or vehicle parts (eg: Tanks and other vehicles) - - `rebalance` - A mod designed to rebalance the game in some way (eg: Safe autodocs). - - `magical` - A mod that adds something magic-related to the game (eg: Necromancy) - - `item_exclude` - A mod that stops items from spawning in the world (eg: No survivor armor, No drugs) - - `monster_exclude` - A mod that stops certain monster varieties from spawning in the world (eg: No fungal monsters, No ants) - - `graphical` - A mod that adjusts game graphics in some way (eg: Graphical overmap) - -The `dependencies` attribute is used to tell Cataclysm that your mod is dependent on something present in another mod. If you have no dependencies outside of the core game, then just including `dda` in the list is good enough. If your mod depends on another one to work properly, adding that mod's `id` attribute to the array causes Cataclysm to force that mod to load before yours. +``` + +The `category` attribute denotes where the mod will appear in the mod selection menu. These are the +available categories to choose from, with some examples chosen from mods that existed when this +document was written. Pick whichever one applies best to your mod when writing your modinfo file. + +- `content` - A mod that adds a lot of stuff. Typically reserved for very large mods or complete + game overhauls (eg: Core game files, Aftershock) +- `items` - A mod that adds new items and recipes to the game (eg: More survival tools) +- `creatures` - A mod that adds new creatures or NPCs to the game (eg: Modular turrets) +- `misc_additions` - Miscellaneous content additions to the game (eg: Alternative map key, Crazy + cataclysm) +- `buildings` - New overmap locations and structures (eg: Fuji's more buildings). If you're + blacklisting buildings from spawning, this is also a usable category (eg: No rail stations). +- `vehicles` - New cars or vehicle parts (eg: Tanks and other vehicles) +- `rebalance` - A mod designed to rebalance the game in some way (eg: Safe autodocs). +- `magical` - A mod that adds something magic-related to the game (eg: Necromancy) +- `item_exclude` - A mod that stops items from spawning in the world (eg: No survivor armor, No + drugs) +- `monster_exclude` - A mod that stops certain monster varieties from spawning in the world (eg: No + fungal monsters, No ants) +- `graphical` - A mod that adjusts game graphics in some way (eg: Graphical overmap) + +The `dependencies` attribute is used to tell Cataclysm that your mod is dependent on something +present in another mod. If you have no dependencies outside of the core game, then just including +`dda` in the list is good enough. If your mod depends on another one to work properly, adding that +mod's `id` attribute to the array causes Cataclysm to force that mod to load before yours. For more details on `MOD_INFO` object, see [JSON_INFO.md](JSON_INFO.md#mod_info). ## Actually adding things to your mod + Now that you have a basic mod, you can get around to actually putting some stuff into it! ### File structure -It's a good idea to put different categories of additions into different json files. Any json files that are present in the mod folder or its subfolders will be detected and read by Cataclysm, but otherwise, there are no restrictions on what you can put where. + +It's a good idea to put different categories of additions into different json files. Any json files +that are present in the mod folder or its subfolders will be detected and read by Cataclysm, but +otherwise, there are no restrictions on what you can put where. ### JSON_INFO.md -It's worth reading [JSON_INFO.md](JSON_INFO.md) to get a comprehensive list of everything you can do with these mods. The rest of this document will have a few examples to copy and paste, but it is by no means comprehensive. The base game's data is also defined in the same way as any mod you write, so taking a look through the game's json files (in `data/json`) can also teach you a lot. If the game finds any issues in your JSON syntax when you try to load a game world, it will spit out an error message, and you won't be able to load that game until the issue is fixed. + +It's worth reading [JSON_INFO.md](JSON_INFO.md) to get a comprehensive list of everything you can do +with these mods. The rest of this document will have a few examples to copy and paste, but it is by +no means comprehensive. The base game's data is also defined in the same way as any mod you write, +so taking a look through the game's json files (in `data/json`) can also teach you a lot. If the +game finds any issues in your JSON syntax when you try to load a game world, it will spit out an +error message, and you won't be able to load that game until the issue is fixed. ### Adding a scenario -Scenarios are what the game uses to determine your general situation when you create a character. They determine when and where your character may spawn in the world, and what professions can be used. They are also used to determine whether those professions can have mutations starting out. Below you will find the JSON definition for the game's built-in `Large Building` scenario. -````json + +Scenarios are what the game uses to determine your general situation when you create a character. +They determine when and where your character may spawn in the world, and what professions can be +used. They are also used to determine whether those professions can have mutations starting out. +Below you will find the JSON definition for the game's built-in `Large Building` scenario. + +```json [ { "type": "scenario", @@ -79,14 +117,18 @@ Scenarios are what the game uses to determine your general situation when you cr "hospital_9" ], "start_name": "In Large Building", - "flags": [ "SUR_START", "CITY_START", "LONE_START" ] + "flags": ["SUR_START", "CITY_START", "LONE_START"] } ] -```` +``` ### Adding a profession. -Professions are what the game calls the character classes you can choose from when the game starts. Professions can start with traits, skills, items, and even pets! Below is the definition for the Police Officer profession: -````json + +Professions are what the game calls the character classes you can choose from when the game starts. +Professions can start with traits, skills, items, and even pets! Below is the definition for the +Police Officer profession: + +```json [ { "type": "profession", @@ -94,29 +136,43 @@ Professions are what the game calls the character classes you can choose from wh "name": "Police Officer", "description": "Just a small-town deputy when you got the call, you were still ready to come to the rescue. Except that soon it was you who needed rescuing - you were lucky to escape with your life. Who's going to respect your authority when the government this badge represents might not even exist anymore?", "points": 2, - "skills": [ { "level": 3, "name": "gun" }, { "level": 3, "name": "pistol" } ], - "traits": [ "PROF_POLICE" ], + "skills": [{ "level": 3, "name": "gun" }, { "level": 3, "name": "pistol" }], + "traits": ["PROF_POLICE"], "items": { "both": { - "items": [ "pants_army", "socks", "badge_deputy", "sheriffshirt", "police_belt", "smart_phone", "boots", "whistle", "wristwatch" ], + "items": [ + "pants_army", + "socks", + "badge_deputy", + "sheriffshirt", + "police_belt", + "smart_phone", + "boots", + "whistle", + "wristwatch" + ], "entries": [ { "group": "charged_two_way_radio" }, - { "item": "ear_plugs", "custom-flags": [ "no_auto_equip" ] }, + { "item": "ear_plugs", "custom-flags": ["no_auto_equip"] }, { "item": "usp_45", "ammo-item": "45_acp", "charges": 12, "container-item": "holster" }, { "item": "legpouch_large", "contents-group": "army_mags_usp45" } ] }, - "male": [ "boxer_shorts" ], - "female": [ "bra", "boy_shorts" ] + "male": ["boxer_shorts"], + "female": ["bra", "boy_shorts"] } } ] -```` +``` ### Adding an item -Items are where you really want to read the [JSON_INFO.md](JSON_INFO.md) file, just because there's so much that you can do with them, and every category of item is a little bit different. + +Items are where you really want to read the [JSON_INFO.md](JSON_INFO.md) file, just because there's +so much that you can do with them, and every category of item is a little bit different. + -````json + +```json [ { "id": "family_photo", @@ -128,21 +184,27 @@ Items are where you really want to read the [JSON_INFO.md](JSON_INFO.md) file, j "weight": "1 g", "volume": 0, "price": 800, - "material": [ "paper" ], + "material": ["paper"], "symbol": "*", "color": "light_gray" } ] -```` +``` ### Preventing monsters from spawning -This kind of mod is relatively simple, but very useful. If you don't want to deal with certain types of monsters in your world, this is how you do it. There are two ways to go about this, and both will be detailed below. You can blacklist entire monster groups, or you can blacklist certain monsters. In order to do either of those things, you need that monster's ID. These can be found in the relevant data files. For the core game, these are in the `data/json/monsters` directory. -The example below is from the `No Ants` mod, and will stop any kind of ant from spawning in-game. -````json + +This kind of mod is relatively simple, but very useful. If you don't want to deal with certain types +of monsters in your world, this is how you do it. There are two ways to go about this, and both will +be detailed below. You can blacklist entire monster groups, or you can blacklist certain monsters. +In order to do either of those things, you need that monster's ID. These can be found in the +relevant data files. For the core game, these are in the `data/json/monsters` directory. The example +below is from the `No Ants` mod, and will stop any kind of ant from spawning in-game. + +```json [ { "type": "MONSTER_BLACKLIST", - "categories": [ "GROUP_ANT", "GROUP_ANT_ACID" ] + "categories": ["GROUP_ANT", "GROUP_ANT_ACID"] }, { "type": "MONSTER_BLACKLIST", @@ -158,74 +220,106 @@ The example below is from the `No Ants` mod, and will stop any kind of ant from ] } ] -```` +``` + ### Preventing locations from spawning + -Preventing certain types of locations from spawning in-game is a little trickier depending on the type of thing you want to target. An overmap building can either be a standard building, or an overmap special. If you want to block things with a specific flag from spawning, you can blacklist those in a very similar manner to monsters. The example below is also from the `No Ants` mod, and stops all anthills from spawning. -````json + +Preventing certain types of locations from spawning in-game is a little trickier depending on the +type of thing you want to target. An overmap building can either be a standard building, or an +overmap special. If you want to block things with a specific flag from spawning, you can blacklist +those in a very similar manner to monsters. The example below is also from the `No Ants` mod, and +stops all anthills from spawning. + +```json [ { "type": "region_overlay", - "regions": [ "all" ], - "overmap_feature_flag_settings": { "blacklist": [ "ANT" ] } + "regions": ["all"], + "overmap_feature_flag_settings": { "blacklist": ["ANT"] } } ] -```` +``` -If the location you want to blacklist is an overmap special, you'll likely have to copy it from its definition, and manually set it's `occurrences` attribute to read `[ 0, 0 ]`. +If the location you want to blacklist is an overmap special, you'll likely have to copy it from its +definition, and manually set it's `occurrences` attribute to read `[ 0, 0 ]`. -Finally, if you're trying to blacklist something that spawns inside of cities, you can do that with a region overlay. The below example is used in the `No rail stations` mod, and stops railroad stations from spawning inside of cities. It doesn't stop the railroad station overmap special from spawning, though. -````json +Finally, if you're trying to blacklist something that spawns inside of cities, you can do that with +a region overlay. The below example is used in the `No rail stations` mod, and stops railroad +stations from spawning inside of cities. It doesn't stop the railroad station overmap special from +spawning, though. + +```json [ { "type": "region_overlay", - "regions": [ "all" ], + "regions": ["all"], "city": { "houses": { "railroad_city": 0 } } } ] -```` +``` ### Disabling certain scenarios -The `SCENARIO_BLACKLIST` can be either a blacklist or a whitelist. -When it is a whitelist, it blacklists all scenarios but the ones specified. -No more than one blacklist can be specified at one time - this is in all json loaded for a particular game (all mods + base game), not just your specific mod. -The format is as follows: + +The `SCENARIO_BLACKLIST` can be either a blacklist or a whitelist. When it is a whitelist, it +blacklists all scenarios but the ones specified. No more than one blacklist can be specified at one +time - this is in all json loaded for a particular game (all mods + base game), not just your +specific mod. The format is as follows: + ```json [ { "type": "SCENARIO_BLACKLIST", "subtype": "whitelist", - "scenarios": [ "largebuilding" ] + "scenarios": ["largebuilding"] } ] ``` -Valid values for `subtype` are `whitelist` and `blacklist`. -`scenarios` is an array of the scenario ids that you want to blacklist or whitelist. + +Valid values for `subtype` are `whitelist` and `blacklist`. `scenarios` is an array of the scenario +ids that you want to blacklist or whitelist. ## Important note on json files -The following characters: `[ { , } ] : "` are *very* important when adding or modifying JSON files. This means a single missing `,` or `[` or `}` can be the difference between a working file and a hanging game at startup. -If you want to include these characters in whatever you are doing (for instance, if you want to put a quote inside an item's description), you can do so by putting a backslash before the relevant character. This is known as "escaping" that character. For instance, I can make an item's description contain a quote if I want by doing this: -````json +The following characters: `[ { , } ] : "` are _very_ important when adding or modifying JSON files. +This means a single missing `,` or `[` or `}` can be the difference between a working file and a +hanging game at startup. If you want to include these characters in whatever you are doing (for +instance, if you want to put a quote inside an item's description), you can do so by putting a +backslash before the relevant character. This is known as "escaping" that character. For instance, I +can make an item's description contain a quote if I want by doing this: + +```json ... "description": "This is a shirt that says \"I wanna kill ALL the zombies\" on the front.", ... -```` +``` In game, that appears like this: `This is a shirt that says "I wanna kill ALL the zombies" on the front.` -Many editors have features that let you track `{ [` and `] }` to see if they're balanced (ie, have a matching opposite); These editors will also respect escaped characters properly. [Notepad++](https://notepad-plus-plus.org/) is a popular, free editor on Windows that contains this feature. On Linux, there are a plethora of options, and you probably already have a preferred one 🙂 +Many editors have features that let you track `{ [` and `] }` to see if they're balanced (ie, have a +matching opposite); These editors will also respect escaped characters properly. +[Notepad++](https://notepad-plus-plus.org/) is a popular, free editor on Windows that contains this +feature. On Linux, there are a plethora of options, and you probably already have a preferred one 🙂 -You may also want to use some online or offline JSON validator, e.g. https://dev.narc.ro/cataclysm/format.html , or `json_formatter` bundled with every release of the game (just drag-and-drop the .json file on it). +You may also want to use some online or offline JSON validator, e.g. +https://dev.narc.ro/cataclysm/format.html , or `json_formatter` bundled with every release of the +game (just drag-and-drop the .json file on it). ## Addendum + + ### No Zombie Revival -This mod is very simple, but it's worth a special section because it does things a little differently than other mods, and documentation on it is tricky to find. -The entire mod can fit into fifteen lines of JSON, and it's presented below. Just copy/paste that into a modinfo.json file, and put it in a new folder in your mods directory. -````json +This mod is very simple, but it's worth a special section because it does things a little +differently than other mods, and documentation on it is tricky to find. + +The entire mod can fit into fifteen lines of JSON, and it's presented below. Just copy/paste that +into a modinfo.json file, and put it in a new folder in your mods directory. + +```json [ { "type": "MOD_INFO", @@ -233,7 +327,7 @@ The entire mod can fit into fifteen lines of JSON, and it's presented below. Jus "name": "Prevent Zombie Revivication", "description": "Disables zombie revival.", "category": "rebalance", - "dependencies": [ "bn" ] + "dependencies": ["bn"] }, { "type": "monster_adjustment", @@ -241,4 +335,4 @@ The entire mod can fit into fifteen lines of JSON, and it's presented below. Jus "flag": { "name": "REVIVES", "value": false } } ] -```` +``` diff --git a/doc/MONSTERS.md b/doc/MONSTERS.md index 55472d67f10d..3d3abcb5e960 100644 --- a/doc/MONSTERS.md +++ b/doc/MONSTERS.md @@ -1,6 +1,7 @@ # Monster types Monster types are specified as JSON object with "type" member set to "MONSTER": + ```JSON { "type": "MONSTER", @@ -9,13 +10,16 @@ Monster types are specified as JSON object with "type" member set to "MONSTER": } ``` -The id member should be the unique id of the type. It can be any string, by convention it has the prefix "mon_". This id can be referred to in various places, like monster groups or in mapgen to spawn specific monsters. +The id member should be the unique id of the type. It can be any string, by convention it has the +prefix "mon_". This id can be referred to in various places, like monster groups or in mapgen to +spawn specific monsters. For quantity strings (ie. volume, weight) use the largest unit you can keep full precision with. Monster types support the following properties (mandatory, except if noted otherwise): ## "name" + (string or object) ```JSON @@ -36,254 +40,330 @@ Name displayed in-game, and optionally the plural name and a translation context If the plural name is not specified, it defaults to singular name + "s". -Ctxt is used to help translators in case of homonyms (two different things with the same name). For example, pike the fish and pike the weapon. +Ctxt is used to help translators in case of homonyms (two different things with the same name). For +example, pike the fish and pike the weapon. ## "description" + (string) In-game description for the monster. ## "categories" + (array of strings, optional) -Monster categories. Can be NULL, CLASSIC (only mobs found in classic zombie movies) or WILDLIFE (natural animals). If they are not CLASSIC or WILDLIFE, they will not spawn in classic mode. One can add or remove entries in mods via "add:flags" and "remove:flags". +Monster categories. Can be NULL, CLASSIC (only mobs found in classic zombie movies) or WILDLIFE +(natural animals). If they are not CLASSIC or WILDLIFE, they will not spawn in classic mode. One can +add or remove entries in mods via "add:flags" and "remove:flags". ## "species" + (array of strings, optional) -A list of species ids. One can add or remove entries in mods via "add:species" and "remove:species", see Modding below. Properties (currently only triggers) from species are added to the properties of each monster that belong to the species. +A list of species ids. One can add or remove entries in mods via "add:species" and "remove:species", +see Modding below. Properties (currently only triggers) from species are added to the properties of +each monster that belong to the species. -In mainline game it can be HUMAN, ROBOT, ZOMBIE, MAMMAL, BIRD, FISH, REPTILE, WORM, MOLLUSK, AMPHIBIAN, INSECT, SPIDER, FUNGUS, PLANT, NETHER, MUTANT, BLOB, HORROR, ABERRATION, HALLUCINATION and UNKNOWN. +In mainline game it can be HUMAN, ROBOT, ZOMBIE, MAMMAL, BIRD, FISH, REPTILE, WORM, MOLLUSK, +AMPHIBIAN, INSECT, SPIDER, FUNGUS, PLANT, NETHER, MUTANT, BLOB, HORROR, ABERRATION, HALLUCINATION +and UNKNOWN. ## "volume" + (string) ```JSON "volume": "40 L" ``` -The numeric part of the string must be an integer. Accepts L, and ml as units. Note that l and mL are not currently accepted. + +The numeric part of the string must be an integer. Accepts L, and ml as units. Note that l and mL +are not currently accepted. ## "weight" + (string) ```JSON "weight": "3 kg" ``` -The numeric part of the string must be an integer. Use the largest unit you can keep full precision with. For example: 3 kg, not 3000 g. Accepts g and kg as units. + +The numeric part of the string must be an integer. Use the largest unit you can keep full precision +with. For example: 3 kg, not 3000 g. Accepts g and kg as units. ## "scent_tracked" + (array of strings, optional) List of scenttype_id tracked by this monster. scent_types are defined in scent_types.json ## "scent_ignored" + (array of strings, optional) List of scenttype_id ignored by this monster. scent_types are defined in scent_types.json ## "symbol", "color" + (string) -Symbol and color representing monster in-game. The symbol must be a UTF-8 string, that is exactly one console cell width (may be several Unicode characters). See [COLOR.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/COLOR.md) for details. +Symbol and color representing monster in-game. The symbol must be a UTF-8 string, that is exactly +one console cell width (may be several Unicode characters). See +[COLOR.md](https://github.com/CleverRaven/Cataclysm-DDA/blob/master/doc/COLOR.md) for details. ## "size" + (string, optional) Size flag, see JSON_FLAGS.md. ## "material" + (array of strings, optional) -The materials the monster is primarily composed of. Must contain valid material ids. An empty array (which is the default) is also allowed, the monster is made of no specific material. One can add or remove entries in mods via "add:material" and "remove:material". +The materials the monster is primarily composed of. Must contain valid material ids. An empty array +(which is the default) is also allowed, the monster is made of no specific material. One can add or +remove entries in mods via "add:material" and "remove:material". ## "phase" + (string, optional) -It describes monster's body state of matter. However, it doesn't seem to have any gameplay purpose, right now. -It can be SOLID, LIQUID, GAS, PLASMA or NULL. +It describes monster's body state of matter. However, it doesn't seem to have any gameplay purpose, +right now. It can be SOLID, LIQUID, GAS, PLASMA or NULL. ## "default_faction" + (string) -The id of the faction the monster belongs to, this affects what other monsters it will fight. See Monster factions. +The id of the faction the monster belongs to, this affects what other monsters it will fight. See +Monster factions. ## "bodytype" + (string) -The id of the monster's bodytype, which is a general description of the layout of the monster's body. +The id of the monster's bodytype, which is a general description of the layout of the monster's +body. Value should be one of: -| value | description -| --- | --- -| angel | a winged human -| bear | a four legged animal that can stand on its hind legs -| bird | a two legged animal with two wings -| blob | a blob of material -| crab | a multilegged animal with two large arms -| quadruped | a four legged animal -| elephant | a very large quadruped animal with a large head and torso with equal sized limbs -| fish | an aquatic animal with a streamlined body and fins -| flying insect | a six legged animal with a head and two body segments and wings -| frog | a four legged animal with a neck and with very large rear legs and small forelegs -| gator | a four legged animal with a very long body and short legs -| human | a bipedal animal with two arms -| insect | a six legged animal with a head and two body segments -| kangaroo | a pentapedal animal that utilizes a large tail for stability with very large rear legs and smaller forearms -| lizard | a smaller form of 'gator' -| migo | whatever form migos have -| pig | a four legged animal with the head in the same line as the body -| spider | an eight legged animal with a small head on a large abdomen -| snake | an animal with a long body and no limbs +| value | description | +| ------------- | ----------------------------------------------------------------------------------------------------------- | +| angel | a winged human | +| bear | a four legged animal that can stand on its hind legs | +| bird | a two legged animal with two wings | +| blob | a blob of material | +| crab | a multilegged animal with two large arms | +| quadruped | a four legged animal | +| elephant | a very large quadruped animal with a large head and torso with equal sized limbs | +| fish | an aquatic animal with a streamlined body and fins | +| flying insect | a six legged animal with a head and two body segments and wings | +| frog | a four legged animal with a neck and with very large rear legs and small forelegs | +| gator | a four legged animal with a very long body and short legs | +| human | a bipedal animal with two arms | +| insect | a six legged animal with a head and two body segments | +| kangaroo | a pentapedal animal that utilizes a large tail for stability with very large rear legs and smaller forearms | +| lizard | a smaller form of 'gator' | +| migo | whatever form migos have | +| pig | a four legged animal with the head in the same line as the body | +| spider | an eight legged animal with a small head on a large abdomen | +| snake | an animal with a long body and no limbs | ## "attack_cost" + (integer, optional) Number of moves per regular attack. ## "diff" + (integer, optional) -Monster baseline difficulty. Impacts the shade used to label the monster, and if it is above 30 a kill will be recorded in the memorial log. Monster difficult is calculated based on expected melee damage, dodge, armor, hit points, speed, morale, aggression, and vision ranges. The calculation does not handle ranged special attacks or unique special attacks very well, and baseline difficulty can be used to account for that. Suggested values: +Monster baseline difficulty. Impacts the shade used to label the monster, and if it is above 30 a +kill will be recorded in the memorial log. Monster difficult is calculated based on expected melee +damage, dodge, armor, hit points, speed, morale, aggression, and vision ranges. The calculation does +not handle ranged special attacks or unique special attacks very well, and baseline difficulty can +be used to account for that. Suggested values: -| value | description -| --- | --- -| 2 | a limited defensive ability such as a skitterbot's taser, or a weak special like a shrieker zombie's special ability to alert nearby monsters, or a minor bonus to attack like poison or venom. -| 5 | a limited ranged attack weaker than spitter zombie's spit, or a powerful defensive ability like a shocker zombie's zapback or an acid zombie's acid spray. -| 10 | a powerful ranged attack, like a spitters zombie's spit or an turret's 9mm SMG. -| 15 | a powerful ranged attack with additional hazards, like a corrosize zombie's spit -| 20 | a very powerful ranged attack, like a laser turret or military turret's 5.56mm rifle, or a powerful special ability, like a zombie necromancer's ability to raise other zombies. -| 30 | a ranged attack that is deadly even for armored characters, like an anti-material turret's .50 BMG rifle. +| value | description | +| ----- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| 2 | a limited defensive ability such as a skitterbot's taser, or a weak special like a shrieker zombie's special ability to alert nearby monsters, or a minor bonus to attack like poison or venom. | +| 5 | a limited ranged attack weaker than spitter zombie's spit, or a powerful defensive ability like a shocker zombie's zapback or an acid zombie's acid spray. | +| 10 | a powerful ranged attack, like a spitters zombie's spit or an turret's 9mm SMG. | +| 15 | a powerful ranged attack with additional hazards, like a corrosize zombie's spit | +| 20 | a very powerful ranged attack, like a laser turret or military turret's 5.56mm rifle, or a powerful special ability, like a zombie necromancer's ability to raise other zombies. | +| 30 | a ranged attack that is deadly even for armored characters, like an anti-material turret's .50 BMG rifle. | -Most monsters should have difficulty 0 - even dangerous monsters like a zombie hulk or razorclaw alpha. Difficulty should only be used for exceptional, ranged, special attacks. +Most monsters should have difficulty 0 - even dangerous monsters like a zombie hulk or razorclaw +alpha. Difficulty should only be used for exceptional, ranged, special attacks. ## "aggression" + (integer, optional) -Defines how aggressive the monster is. Ranges from -99 (totally passive) to 100 (guaranteed hostility on detection) +Defines how aggressive the monster is. Ranges from -99 (totally passive) to 100 (guaranteed +hostility on detection) ## "morale" + (integer, optional) -Monster morale. Defines how low monster HP can get before it retreats. This number is treated as % of their max HP. +Monster morale. Defines how low monster HP can get before it retreats. This number is treated as % +of their max HP. ## "speed" + (integer) -Monster speed. 100 is the normal speed for a human being - higher values are faster and lower values are slower. +Monster speed. 100 is the normal speed for a human being - higher values are faster and lower values +are slower. ## "mountable_weight_ratio" + (float, optional) -Used as the acceptable rider vs. mount weight percentage ratio. Defaults to "0.3", which means the mount is capable of carrying riders weighing <= 30% of the mount's weight. +Used as the acceptable rider vs. mount weight percentage ratio. Defaults to "0.3", which means the +mount is capable of carrying riders weighing <= 30% of the mount's weight. ## "melee_skill" + (integer, optional) -Monster melee skill, ranges from 0 - 10, with 4 being an average mob. See GAME_BALANCE.txt for more examples +Monster melee skill, ranges from 0 - 10, with 4 being an average mob. See GAME_BALANCE.txt for more +examples ## "dodge" + (integer, optional) Monster dodge skill. See GAME_BALANCE.txt for an explanation of dodge mechanics. ## "melee_damage" + (array of objects, optional) -List of damage instances added to die roll on monster melee attack. - - `damage_type` valid entries are : "true", "biological", "bash", "cut", "acid", "stab", "heat", "cold" and "electric". - - `amount` amount of damage. - - `armor_penetration` how much of the armor the damage instance ignores. - - `armor_multiplier` is a multiplier on `armor_penetration`. - - `damage_multiplier` is a multiplier on `amount`. +List of damage instances added to die roll on monster melee attack. - `damage_type` valid entries +are : "true", "biological", "bash", "cut", "acid", "stab", "heat", "cold" and "electric". - `amount` +amount of damage. - `armor_penetration` how much of the armor the damage instance ignores. - +`armor_multiplier` is a multiplier on `armor_penetration`. - `damage_multiplier` is a multiplier on +`amount`. + ```JSON - "melee_damage": [ { "damage_type": "electric", "amount": 4.0, "armor_penetration": 1, "armor_multiplier": 1.2, "damage_multiplier": 1.4 } ], +"melee_damage": [ { "damage_type": "electric", "amount": 4.0, "armor_penetration": 1, "armor_multiplier": 1.2, "damage_multiplier": 1.4 } ], ``` ## "melee_dice", "melee_dice_sides" + (integer, optional) -Number of dices and their sides that are rolled on monster melee attack. This defines the amount of bash damage. +Number of dices and their sides that are rolled on monster melee attack. This defines the amount of +bash damage. ## "grab_strength" + (integer, optional) -Intensity of the grab effect applied by this monster. Defaults to 1, is only useful for monster with a GRAB special attack and the GRABS flag. A monster with grab_strength = n applies a grab as if it was n zombies. A player with max(Str,Dex)<=n has no chance of breaking that grab. +Intensity of the grab effect applied by this monster. Defaults to 1, is only useful for monster with +a GRAB special attack and the GRABS flag. A monster with grab_strength = n applies a grab as if it +was n zombies. A player with max(Str,Dex)<=n has no chance of breaking that grab. ## "melee_cut" + (integer, optional) Amount of cutting damage added to die roll on monster melee attack. ## "armor_bash", "armor_cut", "armor_stab", "armor_acid", "armor_fire" + (integer, optional) Monster protection from bashing, cutting, stabbing, acid and fire damage. ## "vision_day", "vision_night" + (integer, optional) Vision range in full daylight and in total darkness. ## "luminance" + (integer, optional) Amount of light passively output by monster. Ranges from 0 to 10. ## "hp" + (integer) Monster hit points. ## "death_drops" + (string or item group, optional) -An item group that is used to spawn items when the monster dies. This can be an inlined item group, see ITEM_SPAWN.md. The default subtype is "distribution". +An item group that is used to spawn items when the monster dies. This can be an inlined item group, +see ITEM_SPAWN.md. The default subtype is "distribution". ## "death_function" + (array of strings, optional) -How the monster behaves on death. See JSON_FLAGS.md for a list of possible functions. One can add or remove entries in mods via "add:death_function" and "remove:death_function". +How the monster behaves on death. See JSON_FLAGS.md for a list of possible functions. One can add or +remove entries in mods via "add:death_function" and "remove:death_function". ## "emit_field" -(array of objects of emit_id and time_duration, optional) -"emit_fields": [ { "emit_id": "emit_gum_web", "delay": "30 m" } ], -What field the monster emits and how often it does so. Time duration can use strings: "1 h", "60 m", "3600 s" etc... +(array of objects of emit_id and time_duration, optional) "emit_fields": [ { "emit_id": +"emit_gum_web", "delay": "30 m" } ], + +What field the monster emits and how often it does so. Time duration can use strings: "1 h", "60 m", +"3600 s" etc... ## "regenerates" + (integer, optional) Number of hitpoints regenerated per turn. ## "regeneration_modifiers" + ( array of objects consisting of effect, base_mod (float) and scaling_mod (float), optional ) "regeneration_modifiers": [ { "effect": "on_fire", "base_mod": -0.3, "scaling_mod": -0.15 } ], -What effects (if any) affect the monster's regeneration positively/negatively. -The mods stack additively (Intensity 2 on_fire produces a multiplier of 0.45) but are applied multiplicatively. +What effects (if any) affect the monster's regeneration positively/negatively. The mods stack +additively (Intensity 2 on_fire produces a multiplier of 0.45) but are applied multiplicatively. ## "regenerates_in_dark" + (boolean, optional) Monster regenerates very quickly in poorly lit tiles. ## "regen_morale" + (boolean, optional) Will stop fleeing if at max hp, and regen anger and morale. ## "special_attacks" + (array of special attack definitions, optional) -Monster's special attacks. This should be an array, each element of it should be an object (new style) or an array (old style). +Monster's special attacks. This should be an array, each element of it should be an object (new +style) or an array (old style). + +The old style array should contain 2 elements: the id of the attack (see JSON_FLAGS.md for a list) +and the cooldown for that attack. Example (grab attack every 10 turns): -The old style array should contain 2 elements: the id of the attack (see JSON_FLAGS.md for a list) and the cooldown for that attack. Example (grab attack every 10 turns): ```JSON "special_attacks": [ [ "GRAB", 10 ] ] ``` -The new style object should contain at least a "type" member (string) and "cooldown" member (integer). It may contain additional members as required by the specific type. Possible types are listed below. Example: +The new style object should contain at least a "type" member (string) and "cooldown" member +(integer). It may contain additional members as required by the specific type. Possible types are +listed below. Example: + ```JSON "special_attacks": [ { "type": "leap", "cooldown": 10, "max_range": 4 } @@ -291,6 +371,7 @@ The new style object should contain at least a "type" member (string) and "coold ``` "special_attacks" may contain any mixture of old and new style entries: + ```JSON "special_attacks": [ [ "GRAB", 10 ], @@ -298,41 +379,56 @@ The new style object should contain at least a "type" member (string) and "coold ] ``` -One can add entries with "add:death_function", which takes the same content as the "special_attacks" member and remove entries with "remove:death_function", which requires an array of attack types. Example: +One can add entries with "add:death_function", which takes the same content as the "special_attacks" +member and remove entries with "remove:death_function", which requires an array of attack types. +Example: + ```JSON "remove:special_attacks": [ "GRAB" ], "add:special_attacks": [ [ "SHRIEK", 20 ] ] ``` ## "flags" + (array of strings, optional) -Monster flags. See JSON_FLAGS.md for a full list. One can add or remove entries in mods via "add:flags" and "remove:flags". +Monster flags. See JSON_FLAGS.md for a full list. One can add or remove entries in mods via +"add:flags" and "remove:flags". ## "fear_triggers", "anger_triggers", "placate_triggers" + (array of strings, optional) What makes the monster afraid / angry / what calms it. See JSON_FLAGS.md for a full list ## "revert_to_itype" + (string, optional) -If not empty and a valid item id, the monster can be converted into this item by the player, when it's friendly. This is usually used for turrets and similar to revert the turret monster back into the turret item, which can be picked up and placed elsewhere. +If not empty and a valid item id, the monster can be converted into this item by the player, when +it's friendly. This is usually used for turrets and similar to revert the turret monster back into +the turret item, which can be picked up and placed elsewhere. ## "starting_ammo" + (object, optional) -An object containing ammo that newly spawned monsters start with. This is useful for a monster that has a special attack that consumes ammo. Example: +An object containing ammo that newly spawned monsters start with. This is useful for a monster that +has a special attack that consumes ammo. Example: + ```JSON "starting_ammo": { "9mm": 100, "40mm_frag": 100 } ``` ## "upgrades" + (boolean or object, optional) -Controls how this monster is upgraded over time. It can either be the single value `false` (which is the default and disables upgrading) or an object describing the upgrades. +Controls how this monster is upgraded over time. It can either be the single value `false` (which is +the default and disables upgrading) or an object describing the upgrades. Example: + ```JSON "upgrades": { "into_group": "GROUP_ZOMBIE_UPGRADE", @@ -343,57 +439,70 @@ Example: The upgrades object may have the following members: ### "half_life" -(int) -Time in which half of the monsters upgrade according to an approximated exponential progression. It is scaled with the evolution scaling factor which defaults to 4 days. + +(int) Time in which half of the monsters upgrade according to an approximated exponential +progression. It is scaled with the evolution scaling factor which defaults to 4 days. ### "into_group" -(string, optional) -The upgraded monster's type is taken from the specified group. The cost in these groups is for an upgrade in the spawn process (related to the rare "replace_monster_group" and "new_monster_group_id" attributes of spawning groups). + +(string, optional) The upgraded monster's type is taken from the specified group. The cost in these +groups is for an upgrade in the spawn process (related to the rare "replace_monster_group" and +"new_monster_group_id" attributes of spawning groups). ### "into" -(string, optional) -The upgraded monster's type. + +(string, optional) The upgraded monster's type. ### "age_grow" -(int, optional) -Number of days needed for monster to change into another monster. + +(int, optional) Number of days needed for monster to change into another monster. ## "reproduction" -(dictionary, optional) -The monster's reproduction cycle, if any. Supports: + +(dictionary, optional) The monster's reproduction cycle, if any. Supports: ### "baby_monster" -(string, optional) -the id of the monster spawned on reproduction for monsters who give live births. You must declare either this or `baby_egg` for reproduction to work. + +(string, optional) the id of the monster spawned on reproduction for monsters who give live births. +You must declare either this or `baby_egg` for reproduction to work. ### "baby_egg" -(string, optional) -The id of the egg type to spawn for egg-laying monsters. You must declare either this or "baby_monster" for reproduction to work. + +(string, optional) The id of the egg type to spawn for egg-laying monsters. You must declare either +this or "baby_monster" for reproduction to work. ### "baby_count" -(int) -Number of new creatures or eggs to spawn on reproduction. + +(int) Number of new creatures or eggs to spawn on reproduction. ### "baby_timer" -(int) -Number of days between reproduction events. + +(int) Number of days between reproduction events. ## "baby_flags" -(Array, optional) -Designate seasons during which this monster is capable of reproduction. ie: `[ "SPRING", "SUMMER" ]` + +(Array, optional) Designate seasons during which this monster is capable of reproduction. ie: +`[ "SPRING", "SUMMER" ]` ## "special_when_hit" + (array, optional) -A special defense attack, triggered when the monster is attacked. It should contain an array with the id of the defense (see Monster defense attacks in JSON_FLAGS.md) and the chance for that defense to be actually triggered. Example: +A special defense attack, triggered when the monster is attacked. It should contain an array with +the id of the defense (see Monster defense attacks in JSON_FLAGS.md) and the chance for that defense +to be actually triggered. Example: + ```JSON "special_when_hit": [ "ZAPBACK", 100 ] ``` ## "attack_effs" + (array of objects, optional) -A set of effects that may get applied to the attacked creature when the monster successfully attacks. Example: +A set of effects that may get applied to the attacked creature when the monster successfully +attacks. Example: + ```JSON "attack_effs": [ { @@ -407,192 +516,251 @@ A set of effects that may get applied to the attacked creature when the monster Each element of the array should be an object containing the following members: ### "id" + (string) The id of the effect that is to be applied. ### "duration" + (integer, optional) How long (in turns) the effect should last. ### "affect_hit_bp" + (boolean, optional) Whether the effect should be applied to the hit body part instead of the one set below. ### "bp" -(string, optional) -The body part that where the effect is applied. The default is to apply the effect to the whole body. Note that some effects may require a specific body part (e.g. "hot") and others may require the whole body (e.g. "meth"). +(string, optional) +The body part that where the effect is applied. The default is to apply the effect to the whole +body. Note that some effects may require a specific body part (e.g. "hot") and others may require +the whole body (e.g. "meth"). ### "chance" + (integer, optional) The chance of the effect getting applied. - - # Modding -Monster types can be overridden or modified in mods. To do so, one has to add an "edit-mode" member, which can contain either: -- "create" (the default if the member does not exist), an error will be shown if a type with the given id already exists. -- "override", an existing type (if any) with the given id will be removed and the new data will be loaded as a completely new type. -- "modify", an existing type will be modified. If there is no type with the given id, an error will be shown. +Monster types can be overridden or modified in mods. To do so, one has to add an "edit-mode" member, +which can contain either: -Mandatory properties (all that are not marked as optional) are only required if edit mode is "create" or "override". +- "create" (the default if the member does not exist), an error will be shown if a type with the + given id already exists. +- "override", an existing type (if any) with the given id will be removed and the new data will be + loaded as a completely new type. +- "modify", an existing type will be modified. If there is no type with the given id, an error will + be shown. + +Mandatory properties (all that are not marked as optional) are only required if edit mode is +"create" or "override". Example (rename the zombie monster, leaves all other properties untouched): + ```JSON { - "type": "MONSTER", - "edit-mode": "modify", - "id": "mon_zombie", - "name": "clown" + "type": "MONSTER", + "edit-mode": "modify", + "id": "mon_zombie", + "name": "clown" } ``` -The default edit mode ("create") is suitable for new types, if their id conflicts with the types from other mods or from the core data, an error will be shown. The edit mode "override" is suitable for re-defining a type from scratch, it ensures that all mandatory members are listed and leaves no traces of the previous definitions. Edit mode "modify" is for small changes, like adding a flag or removing a special attack. -Modifying a type overrides the properties with the new values, this example sets the special attacks to contain *only* the "SHRIEK" attack: +The default edit mode ("create") is suitable for new types, if their id conflicts with the types +from other mods or from the core data, an error will be shown. The edit mode "override" is suitable +for re-defining a type from scratch, it ensures that all mandatory members are listed and leaves no +traces of the previous definitions. Edit mode "modify" is for small changes, like adding a flag or +removing a special attack. + +Modifying a type overrides the properties with the new values, this example sets the special attacks +to contain _only_ the "SHRIEK" attack: + ```JSON { - "type": "MONSTER", - "edit-mode": "modify", - "id": "mon_zombie", - "special_attacks": [ [ "SHRIEK", 20 ] ] + "type": "MONSTER", + "edit-mode": "modify", + "id": "mon_zombie", + "special_attacks": [["SHRIEK", 20]] } ``` -Some properties allow adding and removing entries, as documented above, usually via members with the "add:"/"remove:" prefix. - +Some properties allow adding and removing entries, as documented above, usually via members with the +"add:"/"remove:" prefix. # Monster special attack types + The listed attack types can be as monster special attacks (see "special_attacks"). ## "leap" + Makes the monster leap a few tiles. It supports the following additional properties: ### "max_range" + (Required) Maximal range of attack. ### "min_range" + (Required) Minimal range needed for attack. ### "allow_no_target" + This prevents monster from using the ability on empty space. ### "move_cost" + Turns needed to complete special attack. 100 move_cost with 100 speed is equal to 1 second/turn. #### "min_consider_range", "max_consider_range" + Minimal range and maximal range to consider for using specific attack. ## "bite" + Makes monster use teeth to bite opponent. Some monsters can give infection by doing so. ### "damage_max_instance" + Max damage it can deal on one bite. ### "min_mul", "max_mul" + How hard is to get free of bite without killing attacker. ### "move_cost" + Turns needed to complete special attack. 100 move_cost with 100 speed is equal to 1 second/turn. ### "accuracy" + (Integer) How accurate it is. Not many monsters use it though. ### "no_infection_chance" + Chance to not give infection. ## "gun" + Fires a gun at a target. If friendly, will avoid harming the player. ### "gun_type" + (Required) Valid item id of a gun that will be used to perform the attack. ### "ammo_type" -(Required) Valid item id of the ammo the gun will be loaded with. -Monster should also have a "starting_ammo" field with this ammo. -For example + +(Required) Valid item id of the ammo the gun will be loaded with. Monster should also have a +"starting_ammo" field with this ammo. For example + ``` "ammo_type" : "50bmg", "starting_ammo" : {"50bmg":100} ``` ### "max_ammo" + Cap on ammo. If ammo goes above this value for any reason, a debug message will be printed. ### "fake_str" + Strength stat of the fake NPC that will execute the attack. 8 if not specified. ### "fake_dex" + Dexterity stat of the fake NPC that will execute the attack. 8 if not specified. ### "fake_int" + Intelligence stat of the fake NPC that will execute the attack. 8 if not specified. ### "fake_per" + Perception stat of the fake NPC that will execute the attack. 8 if not specified. ### "fake_skills" + Array of 2 element arrays of skill id and skill level pairs. ### "move_cost" + Move cost of executing the attack // If true, gives "grace period" to player + ### "require_targeting_player" -If true, the monster will need to "target" the player, -wasting `targeting_cost` moves, putting the attack on cooldown and making warning sounds, -unless it attacked something that needs to be targeted recently. + +If true, the monster will need to "target" the player, wasting `targeting_cost` moves, putting the +attack on cooldown and making warning sounds, unless it attacked something that needs to be targeted +recently. ### "require_targeting_npc" + As above, but with npcs. ### "require_targeting_monster" + As above, but with monsters. ### "targeting_timeout" -Targeting status will be applied for this many turns. -Note that targeting applies to turret, not targets. + +Targeting status will be applied for this many turns. Note that targeting applies to turret, not +targets. ### "targeting_timeout_extend" + Successfully attacking will extend the targeting for this many turns. Can be negative. ### "targeting_cost" -Move cost of targeting the player. Only applied if attacking the player and didn't target player within last 5 turns. + +Move cost of targeting the player. Only applied if attacking the player and didn't target player +within last 5 turns. ### "no_crits" -If true then attacking create will be unable to score ranged critical hit on target, -also good hits no longer has high change to go to the head, instead there is high change to score hit to the body and limbs. -If false then default behavior used - critical hits are allowed and good hit has high chance to reach head. + +If true then attacking create will be unable to score ranged critical hit on target, also good hits +no longer has high change to go to the head, instead there is high change to score hit to the body +and limbs. If false then default behavior used - critical hits are allowed and good hit has high +chance to reach head. ### "laser_lock" -If true and attacking a creature that isn't laser-locked but needs to be targeted, -the monster will act as if it had no targeting status (and waste time targeting), -the target will become laser-locked, and if the target is the player, it will cause a warning. + +If true and attacking a creature that isn't laser-locked but needs to be targeted, the monster will +act as if it had no targeting status (and waste time targeting), the target will become +laser-locked, and if the target is the player, it will cause a warning. Laser-locking affects the target, but isn't tied to specific attacker. ### "range" + Maximum range at which targets will be acquired. ### "range_no_burst" + Maximum range at which targets will be attacked with a burst (if applicable). ### "burst_limit" + Limit on burst size. ### "description" + Description of the attack being executed if seen by the player. ### "targeting_sound" + Description of the sound made when targeting. ### "targeting_volume" + Volume of the sound made when targeting. ### "no_ammo_sound" + Description of the sound made when out of ammo. diff --git a/doc/NPCs.md b/doc/NPCs.md index 24c9d5a9b5c0..6e125f16bd7d 100644 --- a/doc/NPCs.md +++ b/doc/NPCs.md @@ -1,7 +1,10 @@ TODO: document the "npc" structure, used to load NPC template # Writing dialogues -Dialogues work like state machines. They start with a certain topic (the NPC says something), the player character can respond (choosing one of several responses), and that response sets the new talk topic. This goes on until the dialogue is finished, or the NPC turns hostile. + +Dialogues work like state machines. They start with a certain topic (the NPC says something), the +player character can respond (choosing one of several responses), and that response sets the new +talk topic. This goes on until the dialogue is finished, or the NPC turns hostile. Note that it is perfectly fine to have a response that switches the topic back to itself. @@ -9,15 +12,17 @@ NPC missions are controlled by a separate but related JSON structure and are doc [the missions docs](MISSIONS_JSON.md). Two topics are special: + - `TALK_DONE` ends the dialogue immediately. - `TALK_NONE` goes to the previously talked about topic. - ### Validating Dialogues + Keeping track of talk topics and making sure that all the topics referenced in responses are -defined, and all defined topics are referenced in a response or an NPC's chat, is very tricky. -There is a python script in `tools/dialogue_validator.py` that will map all topics to responses -and vice versa. Invoke it with +defined, and all defined topics are referenced in a response or an NPC's chat, is very tricky. There +is a python script in `tools/dialogue_validator.py` that will map all topics to responses and vice +versa. Invoke it with + ```sh python tools/dialogue_validator.py data/json/npcs/* data/json/npcs/Backgrounds/* data/json/npcs/refugee_center/* ``` @@ -27,39 +32,51 @@ If you are writing a mod with dialogue, you can add the paths to the mod's dialo ## Talk topics Each topic consists of: + 1. a topic id (e.g. `TALK_ARSONIST`) 2. a dynamic line, spoken by the NPC. 3. an optional list of effects that occur when the NPC speaks the dynamic line 4. a list of responses that can be spoken by the player character. -5. a list of repeated responses that can be spoken by the player character, automatically generated if the player or NPC has items in a list of items. +5. a list of repeated responses that can be spoken by the player character, automatically generated + if the player or NPC has items in a list of items. -One can specify new topics in json. It is currently not possible to define the starting topic, so you have to add a response to some of the default topics (e.g. `TALK_STRANGER_FRIENDLY` or `TALK_STRANGER_NEUTRAL`) or to topics that can be reached somehow. +One can specify new topics in json. It is currently not possible to define the starting topic, so +you have to add a response to some of the default topics (e.g. `TALK_STRANGER_FRIENDLY` or +`TALK_STRANGER_NEUTRAL`) or to topics that can be reached somehow. Format: + ```json { - "type": "talk_topic", - "id": "TALK_ARSONIST", - "dynamic_line": "What now?", - "responses": [ - { - "text": "I don't know either", - "topic": "TALK_DONE" - } - ], - "replace_built_in_responses": true + "type": "talk_topic", + "id": "TALK_ARSONIST", + "dynamic_line": "What now?", + "responses": [ + { + "text": "I don't know either", + "topic": "TALK_DONE" + } + ], + "replace_built_in_responses": true } ``` ### type + Must always be there and must always be `"talk_topic"`. ### id -The topic id can be one of the built-in topics or a new id. However, if several talk topics *in json* have the same id, the last topic definition will override the previous ones. -The topic id can also be an array of strings. This is loaded as if several topics with the exact same content have been given in json, each associated with an id from the `id`, array. Note that loading from json will append responses and, if defined in json, override the `dynamic_line` and the `replace_built_in_responses` setting. This allows adding responses to several topics at once. +The topic id can be one of the built-in topics or a new id. However, if several talk topics _in +json_ have the same id, the last topic definition will override the previous ones. + +The topic id can also be an array of strings. This is loaded as if several topics with the exact +same content have been given in json, each associated with an id from the `id`, array. Note that +loading from json will append responses and, if defined in json, override the `dynamic_line` and the +`replace_built_in_responses` setting. This allows adding responses to several topics at once. This example adds the "I'm going now!" response to all the listed topics. + ```C++ { "type": "talk_topic", @@ -75,23 +92,40 @@ This example adds the "I'm going now!" response to all the listed topics. ``` ### dynamic_line -The `dynamic_line` is the line spoken by the NPC. It is optional. If it is not defined and the topic has the same id as a built-in topic, the `dynamic_line` from that built-in topic will be used. Otherwise the NPC will say nothing. See the chapter about `dynamic_line` below for more details. + +The `dynamic_line` is the line spoken by the NPC. It is optional. If it is not defined and the topic +has the same id as a built-in topic, the `dynamic_line` from that built-in topic will be used. +Otherwise the NPC will say nothing. See the chapter about `dynamic_line` below for more details. ### speaker_effect -The `speaker_effect` is an object or array of effects that will occur after the NPC speaks the `dynamic_line`, no matter which response the player chooses. See the chapter about Speaker Effects below for more details. + +The `speaker_effect` is an object or array of effects that will occur after the NPC speaks the +`dynamic_line`, no matter which response the player chooses. See the chapter about Speaker Effects +below for more details. ### response -The `responses` entry is an array with possible responses. It must not be empty. Each entry must be a response object. See the chapter about Responses below for more details. + +The `responses` entry is an array with possible responses. It must not be empty. Each entry must be +a response object. See the chapter about Responses below for more details. ### replace_built_in_responses -`replace_built_in_responses` is an optional boolean that defines whether to dismiss the built-in responses for that topic (default is `false`). If there are no built-in responses, this won't do anything. If `true`, the built-in responses are ignored and only those from this definition in the current json are used. If `false`, the responses from the current json are used along with the built-in responses (if any). + +`replace_built_in_responses` is an optional boolean that defines whether to dismiss the built-in +responses for that topic (default is `false`). If there are no built-in responses, this won't do +anything. If `true`, the built-in responses are ignored and only those from this definition in the +current json are used. If `false`, the responses from the current json are used along with the +built-in responses (if any). --- ## dynamic_line -A dynamic line can either be a simple string, or an complex object, or an array with `dynamic_line` entries. If it's an array, an entry will be chosen randomly every time the NPC needs it. Each entry has the same probability. + +A dynamic line can either be a simple string, or an complex object, or an array with `dynamic_line` +entries. If it's an array, an entry will be chosen randomly every time the NPC needs it. Each entry +has the same probability. Example: + ```json "dynamic_line": [ "generic text", @@ -102,65 +136,83 @@ Example: ] ``` -A complex `dynamic_line` usually contains several `dynamic_line` entry and some condition that determines which is used. If dynamic lines are not nested, they are processed in the order of the entries below. The possible types of lines follow. +A complex `dynamic_line` usually contains several `dynamic_line` entry and some condition that +determines which is used. If dynamic lines are not nested, they are processed in the order of the +entries below. The possible types of lines follow. -In all cases, `npc_` refers to the NPC, and `u_` refers to the player. Optional lines do not have to be defined, but the NPC should always have something to say. Entries are always parsed as `dynamic_line` and can be nested. +In all cases, `npc_` refers to the NPC, and `u_` refers to the player. Optional lines do not have to +be defined, but the NPC should always have something to say. Entries are always parsed as +`dynamic_line` and can be nested. #### Several lines joined together -The dynamic line is a list of dynamic lines, all of which are displayed. The dynamic lines in the list are processed normally. + +The dynamic line is a list of dynamic lines, all of which are displayed. The dynamic lines in the +list are processed normally. + ```json { - "and": [ - { - "npc_male": true, - "yes": "I'm a man.", - "no": "I'm a woman." - }, - " ", - { - "u_female": true, - "no": "You're a man.", - "yes": "You're a woman." - } - ] + "and": [ + { + "npc_male": true, + "yes": "I'm a man.", + "no": "I'm a woman." + }, + " ", + { + "u_female": true, + "no": "You're a man.", + "yes": "You're a woman." + } + ] } ``` #### A line to be translated with gender context -The line is to be given a gender context for the NPC, player, or both, to aid -translation in languages where that matters. For example: + +The line is to be given a gender context for the NPC, player, or both, to aid translation in +languages where that matters. For example: + ```json { - "gendered_line": "Thank you.", - "relevant_genders": [ "npc" ] + "gendered_line": "Thank you.", + "relevant_genders": ["npc"] } ``` + ("Thank you" is different for male and female speakers in e.g. Portuguese). -Valid choices for entries in the `"relevant_genders"` list are `"npc"` and -`"u"`. +Valid choices for entries in the `"relevant_genders"` list are `"npc"` and `"u"`. #### A randomly selected hint + The dynamic line will be randomly chosen from the hints snippets. ```json { - "give_hint": true + "give_hint": true } ``` #### Based on a previously generated reason -The dynamic line will be chosen from a reason generated by an earlier effect. The reason will be cleared. Use of it should be gated on the `"has_reason"` condition. + +The dynamic line will be chosen from a reason generated by an earlier effect. The reason will be +cleared. Use of it should be gated on the `"has_reason"` condition. ```json { - "has_reason": { "use_reason": true }, - "no": "What is it, boss?" + "has_reason": { "use_reason": true }, + "no": "What is it, boss?" } ``` #### Based on any Dialogue condition -The dynamic line will be chosen based on whether a single dialogue condition is true or false. Dialogue conditions cannot be chained via `"and"`, `"or"`, or `"not"`. If the condition is true, the `"yes"` response will be chosen and otherwise the `"no"` response will be chosen. Both the `'"yes"` and `"no"` reponses are optional. Simple string conditions may be followed by `"true"` to make them fields in the dynamic line dictionary, or they can be followed by the response that will be chosen if the condition is true and the `"yes"` response can be omitted. + +The dynamic line will be chosen based on whether a single dialogue condition is true or false. +Dialogue conditions cannot be chained via `"and"`, `"or"`, or `"not"`. If the condition is true, the +`"yes"` response will be chosen and otherwise the `"no"` response will be chosen. Both the `'"yes"` +and `"no"` reponses are optional. Simple string conditions may be followed by `"true"` to make them +fields in the dynamic line dictionary, or they can be followed by the response that will be chosen +if the condition is true and the `"yes"` response can be omitted. ```json { @@ -193,12 +245,18 @@ The dynamic line will be chosen based on whether a single dialogue condition is } } ``` + --- ## Speaker Effects -The `speaker_effect` entry contains dialogue effects that occur after the NPC speaks the `dynamic_line` but before the player responds and regardless of the player response. Each effect can have an optional condition, and will only be applied if the condition is true. Each `speaker_effect` can also have an optional `sentinel`, which guarantees the effect will only run once. + +The `speaker_effect` entry contains dialogue effects that occur after the NPC speaks the +`dynamic_line` but before the player responds and regardless of the player response. Each effect can +have an optional condition, and will only be applied if the condition is true. Each `speaker_effect` +can also have an optional `sentinel`, which guarantees the effect will only run once. Format: + ```json "speaker_effect": { "sentinel": "...", @@ -206,7 +264,9 @@ Format: "effect": "..." } ``` + or: + ```json "speaker_effect": [ { @@ -222,70 +282,95 @@ or: ] ``` -The `sentinel` can be any string, but sentinels are unique to each `TALK_TOPIC`. If there are multiple `speaker_effect`s within the `TALK_TOPIC`, they should have different sentinels. Sentinels are not required, but since the `speaker_effect` will run every time the dialogue returns to the `TALK_TOPIC`, they are highly encouraged to avoid inadvertently repeating the same effects. +The `sentinel` can be any string, but sentinels are unique to each `TALK_TOPIC`. If there are +multiple `speaker_effect`s within the `TALK_TOPIC`, they should have different sentinels. Sentinels +are not required, but since the `speaker_effect` will run every time the dialogue returns to the +`TALK_TOPIC`, they are highly encouraged to avoid inadvertently repeating the same effects. -The `effect` can be any legal effect, as described below. The effect can be a simple string, object, or an array of strings and objects, as normal for objects. +The `effect` can be any legal effect, as described below. The effect can be a simple string, object, +or an array of strings and objects, as normal for objects. -The optional `condition` can be any legal condition, as described below. If a `condition` is present, the `effect` will only occur if the `condition` is true. +The optional `condition` can be any legal condition, as described below. If a `condition` is +present, the `effect` will only occur if the `condition` is true. -Speaker effects are useful for setting status variables to indicate that player has talked to the NPC without complicating the responses with multiple effect variables. They can also be used, with a sentinel, to run a `mapgen_update` effect the first time the player hears some dialogue from the NPC. +Speaker effects are useful for setting status variables to indicate that player has talked to the +NPC without complicating the responses with multiple effect variables. They can also be used, with a +sentinel, to run a `mapgen_update` effect the first time the player hears some dialogue from the +NPC. --- + ## Responses -A response contains at least a text, which is display to the user and "spoken" by the player character (its content has no meaning for the game) and a topic to which the dialogue will switch to. It can also have a trial object which can be used to either lie, persuade or intimidate the NPC, see below for details. There can be different results, used either when the trial succeeds and when it fails. + +A response contains at least a text, which is display to the user and "spoken" by the player +character (its content has no meaning for the game) and a topic to which the dialogue will switch +to. It can also have a trial object which can be used to either lie, persuade or intimidate the NPC, +see below for details. There can be different results, used either when the trial succeeds and when +it fails. Format: + ```json { - "text": "I, the player, say to you...", - "condition": "...something...", - "trial": { - "type": "PERSUADE", - "difficulty": 10 - }, - "success": { - "topic": "TALK_DONE", - "effect": "...", - "opinion": { - "trust": 0, - "fear": 0, - "value": 0, - "anger": 0, - "owed": 0, - "favors": 0 - } - }, - "failure": { - "topic": "TALK_DONE" + "text": "I, the player, say to you...", + "condition": "...something...", + "trial": { + "type": "PERSUADE", + "difficulty": 10 + }, + "success": { + "topic": "TALK_DONE", + "effect": "...", + "opinion": { + "trust": 0, + "fear": 0, + "value": 0, + "anger": 0, + "owed": 0, + "favors": 0 } + }, + "failure": { + "topic": "TALK_DONE" + } } ``` Alternatively a short format: + ```json { - "text": "I, the player, say to you...", - "effect": "...", - "topic": "TALK_WHATEVER" + "text": "I, the player, say to you...", + "effect": "...", + "topic": "TALK_WHATEVER" } ``` + The short format is equivalent to (an unconditional switching of the topic, `effect` is optional): + ```json { - "text": "I, the player, say to you...", - "trial": { - "type": "NONE" - }, - "success": { - "effect": "...", - "topic": "TALK_WHATEVER" - } + "text": "I, the player, say to you...", + "trial": { + "type": "NONE" + }, + "success": { + "effect": "...", + "topic": "TALK_WHATEVER" + } } ``` -The optional boolean keys "switch" and "default" are false by default. Only the first response with `"switch": true`, `"default": false`, and a valid condition will be displayed, and no other responses with `"switch": true` will be displayed. If no responses with `"switch": true` and `"default": false` are displayed, then any and all responses with `"switch": true` and `"default": true` will be displayed. In either case, all responses that have `"switch": false` (whether or not they have `"default": true` is set) will be displayed as long their conditions are satisfied. +The optional boolean keys "switch" and "default" are false by default. Only the first response with +`"switch": true`, `"default": false`, and a valid condition will be displayed, and no other +responses with `"switch": true` will be displayed. If no responses with `"switch": true` and +`"default": false` are displayed, then any and all responses with `"switch": true` and +`"default": true` will be displayed. In either case, all responses that have `"switch": false` +(whether or not they have `"default": true` is set) will be displayed as long their conditions are +satisfied. #### switch and default Example + ```json "responses": [ { "text": "You know what, never mind.", "topic": "TALK_NONE" }, @@ -300,51 +385,77 @@ The optional boolean keys "switch" and "default" are false by default. Only the { "text": "Gotta go!", "topic": "TALK_DONE" } ] ``` + The player will always have the option to return to a previous topic or end the conversation, and -will otherwise have the option to give a $500, $50, or $5 bribe if they have the funds. If they +will otherwise have the option to give a $500, $50, or $5 bribe if they have the funds. If they don't have at least $50, they will also have the option to provide some other bribe. ### truefalsetext -The player will have one response text if a condition is true, and another if it is false, but the same trial for either line. `condition`, `true`, and `false` are all mandatory. + +The player will have one response text if a condition is true, and another if it is false, but the +same trial for either line. `condition`, `true`, and `false` are all mandatory. ```json { - "truefalsetext": { - "condition": { "u_has_item": "FMCNote" }, - "true": "I may have the money, I'm not giving you any.", - "false": "I don't have that money." - }, - "topic": "TALK_WONT_PAY" + "truefalsetext": { + "condition": { "u_has_item": "FMCNote" }, + "true": "I may have the money, I'm not giving you any.", + "false": "I don't have that money." + }, + "topic": "TALK_WONT_PAY" } ``` ### text + Will be shown to the user, no further meaning. ### trial -Optional, if not defined, `"NONE"` is used. Otherwise one of `"NONE"`, `"LIE"`, `"PERSUADE"`, `"INTIMIDATE"`, or `"CONDITION"`. If `"NONE"` is used, the `failure` object is not read, otherwise it's mandatory. -The `difficulty` is only required if type is not `"NONE"` or `"CONDITION"` and specifies the success chance in percent (it is however modified by various things like mutations). Higher difficulties are easier to pass. +Optional, if not defined, `"NONE"` is used. Otherwise one of `"NONE"`, `"LIE"`, `"PERSUADE"`, +`"INTIMIDATE"`, or `"CONDITION"`. If `"NONE"` is used, the `failure` object is not read, otherwise +it's mandatory. -An optional `mod` array takes any of the following modifiers and increases the difficulty by the NPC's opinion of your character or personality trait for that modifier multiplied by the value: `"ANGER"`, `"FEAR"`, `"TRUST"`, `"VALUE"`, `"AGRESSION"`, `"ALTRUISM"`, `"BRAVERY"`, `"COLLECTOR"`. The special `"POS_FEAR"` modifier treats NPC's fear of your character below 0 as though it were 0. The special `"TOTAL"` modifier sums all previous modifiers and then multiplies the result by its value and is used when setting the owed value. +The `difficulty` is only required if type is not `"NONE"` or `"CONDITION"` and specifies the success +chance in percent (it is however modified by various things like mutations). Higher difficulties are +easier to pass. -`"CONDITION"` trials take a mandatory `condition` instead of `difficulty`. The `success` object is chosen if the `condition` is true and the `failure` is chosen otherwise. +An optional `mod` array takes any of the following modifiers and increases the difficulty by the +NPC's opinion of your character or personality trait for that modifier multiplied by the value: +`"ANGER"`, `"FEAR"`, `"TRUST"`, `"VALUE"`, `"AGRESSION"`, `"ALTRUISM"`, `"BRAVERY"`, `"COLLECTOR"`. +The special `"POS_FEAR"` modifier treats NPC's fear of your character below 0 as though it were 0. +The special `"TOTAL"` modifier sums all previous modifiers and then multiplies the result by its +value and is used when setting the owed value. + +`"CONDITION"` trials take a mandatory `condition` instead of `difficulty`. The `success` object is +chosen if the `condition` is true and the `failure` is chosen otherwise. ### success and failure -Both objects have the same structure. `topic` defines which topic the dialogue will switch to. `opinion` is optional, if given it defines how the opinion of the NPC will change. The given values are *added* to the opinion of the NPC, they are all optional and default to 0. `effect` is a function that is executed after choosing the response, see below. + +Both objects have the same structure. `topic` defines which topic the dialogue will switch to. +`opinion` is optional, if given it defines how the opinion of the NPC will change. The given values +are _added_ to the opinion of the NPC, they are all optional and default to 0. `effect` is a +function that is executed after choosing the response, see below. The opinion of the NPC affects several aspects of the interaction with NPCs: + - Higher trust makes it easier to lie and persuade, and it usually a good thing. -- Higher fear makes it easier to intimidate, but the NPC may flee from you (and will not talk to you). -- Higher value makes it easier to persuade them and to give them orders, it's a kind of a friendship indicator. -- High anger value (about 20 points more than fear, but this also depends on the NPCs personality) makes the NPC hostile and is usually a bad thing. -The combination of fear and trust decide together with the personality of the NPC the initial talk topic (`"TALK_MUG"`, `"TALK_STRANGER_AGGRESSIVE"`, `"TALK_STRANGER_SCARED"`, `"TALK_STRANGER_WARY"`, `"TALK_STRANGER_FRIENDLY"`, or `"TALK_STRANGER_NEUTRAL"`). +- Higher fear makes it easier to intimidate, but the NPC may flee from you (and will not talk to + you). +- Higher value makes it easier to persuade them and to give them orders, it's a kind of a friendship + indicator. +- High anger value (about 20 points more than fear, but this also depends on the NPCs personality) + makes the NPC hostile and is usually a bad thing. The combination of fear and trust decide + together with the personality of the NPC the initial talk topic (`"TALK_MUG"`, + `"TALK_STRANGER_AGGRESSIVE"`, `"TALK_STRANGER_SCARED"`, `"TALK_STRANGER_WARY"`, + `"TALK_STRANGER_FRIENDLY"`, or `"TALK_STRANGER_NEUTRAL"`). For the actual usage of that data, search the source code for `"op_of_u"`. The `failure` object is used if the trial fails, the `success` object is used otherwise. ### Sample trials + ```json "trial": { "type": "PERSUADE", "difficulty": 0, "mod": [ [ "TRUST", 3 ], [ "VALUE", 3 ], [ "ANGER", -3 ] ] } "trial": { "type": "INTIMIDATE", "difficulty": 20, "mod": [ [ "FEAR", 8 ], [ "VALUE", 2 ], [ "TRUST", 2 ], [ "BRAVERY", -2 ] ] } @@ -365,145 +476,172 @@ The `failure` object is used if the trial fails, the `success` object is used ot ``` ### condition -This is an optional condition which can be used to prevent the response under certain circumstances. If not defined, it defaults to always `true`. If the condition is not met, the response is not included in the list of possible responses. For possible content see Dialogue Conditions below. + +This is an optional condition which can be used to prevent the response under certain circumstances. +If not defined, it defaults to always `true`. If the condition is not met, the response is not +included in the list of possible responses. For possible content see Dialogue Conditions below. --- ## Repeat Responses -Repeat responses are responses that should be added to the response list multiple times, once for each instance of an item. + +Repeat responses are responses that should be added to the response list multiple times, once for +each instance of an item. A repeat response has the following format: + ```json { "for_item": [ - "jerky", "meat_smoked", "fish_smoked", "cooking_oil", "cooking_oil2", "cornmeal", "flour", - "fruit_wine", "beer", "sugar" + "jerky", + "meat_smoked", + "fish_smoked", + "cooking_oil", + "cooking_oil2", + "cornmeal", + "flour", + "fruit_wine", + "beer", + "sugar" ], "response": { "text": "Delivering .", "topic": "TALK_DELIVER_ASK" } } ``` -`"response"` is mandatory and must be a standard dialogue response, as described above. `"switch"` is allowed in repeat responses and works normally. +`"response"` is mandatory and must be a standard dialogue response, as described above. `"switch"` +is allowed in repeat responses and works normally. -One of `"for_item"` or `"for_category"`, and each can either be a single string or list of items or item categories. The `response` is generated for each item in the list in the player or NPC's inventory. +One of `"for_item"` or `"for_category"`, and each can either be a single string or list of items or +item categories. The `response` is generated for each item in the list in the player or NPC's +inventory. -`"is_npc"` is an optional bool value, and if it is present, the NPC's inventory list is checked. By default, the player's inventory list is checked. +`"is_npc"` is an optional bool value, and if it is present, the NPC's inventory list is checked. By +default, the player's inventory list is checked. -`"include_containers"` is an optional bool value, and if it is present, items containing an item will generate separate responses from the item itself. +`"include_containers"` is an optional bool value, and if it is present, items containing an item +will generate separate responses from the item itself. --- ## Dialogue Effects -The `effect` field of `speaker_effect` or a `response` can be any of the following effects. Multiple effects should be arranged in a list and are processed in the order listed. + +The `effect` field of `speaker_effect` or a `response` can be any of the following effects. Multiple +effects should be arranged in a list and are processed in the order listed. #### Missions -Effect | Description ----|--- -`assign_mission` | Assigns a previously selected mission to your character. -`mission_success` | Resolves the current mission successfully. -`mission_failure` | Resolves the current mission as a failure. -`clear_mission` | Clears the mission from the your character's assigned missions. -`mission_reward` | Gives the player the mission's reward. +| Effect | Description | +| ----------------- | --------------------------------------------------------------- | +| `assign_mission` | Assigns a previously selected mission to your character. | +| `mission_success` | Resolves the current mission successfully. | +| `mission_failure` | Resolves the current mission as a failure. | +| `clear_mission` | Clears the mission from the your character's assigned missions. | +| `mission_reward` | Gives the player the mission's reward. | #### Stats / Morale -Effect | Description ----|--- -`give_aid` | Removes all bites, infection, and bleeding from your character's body and heals 10-25 HP of injury on each of your character's body parts. Takes 30 minutes. NPC receives 30 minutes of `currently_busy` effect on start. -`give_aid_all` | Performs `give_aid` on your character and each of your character's NPC allies in crafting range. Takes 1 hour. NPC receives 1 hour of `currently_busy` effect on start. -`buy_haircut` | Gives your character a haircut morale boost for 12 hours. -`buy_shave` | Gives your character a shave morale boost for 6 hours. -`morale_chat` | Gives your character a pleasant conversation morale boost for 6 hours. -`player_weapon_away` | Makes your character put away (unwield) their weapon. -`player_weapon_drop` | Makes your character drop their weapon. +| Effect | Description | +| -------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `give_aid` | Removes all bites, infection, and bleeding from your character's body and heals 10-25 HP of injury on each of your character's body parts. Takes 30 minutes. NPC receives 30 minutes of `currently_busy` effect on start. | +| `give_aid_all` | Performs `give_aid` on your character and each of your character's NPC allies in crafting range. Takes 1 hour. NPC receives 1 hour of `currently_busy` effect on start. | +| `buy_haircut` | Gives your character a haircut morale boost for 12 hours. | +| `buy_shave` | Gives your character a shave morale boost for 6 hours. | +| `morale_chat` | Gives your character a pleasant conversation morale boost for 6 hours. | +| `player_weapon_away` | Makes your character put away (unwield) their weapon. | +| `player_weapon_drop` | Makes your character drop their weapon. | #### Character effects / Mutations -Effect | Description ----|--- -`u_add_effect: effect_string`, (*one of* `duration: duration_string`, `duration: duration_int`)
`npc_add_effect: effect_string`, (*one of* `duration: duration_string`, `duration: duration_int`) | Your character or the NPC will gain the effect for `duration_string` or `duration_int` turns. If `duration_string` is `"PERMANENT"`, the effect will be added permanently. -`u_add_trait: trait_string`
`npc_add_trait: trait_string` | Your character or the NPC will gain the trait. -`u_lose_effect: effect_string`
`npc_lose_effect: effect_string` | Your character or the NPC will lose the effect if they have it. -`u_lose_trait: trait_string`
`npc_lose_trait: trait_string` | Your character or the NPC will lose the trait. -`u_add_var, npc_add_var`: `var_name, type: type_str`, `context: context_str`, `value: value_str` | Your character or the NPC will store `value_str` as a variable that can be later retrieved by `u_has_var` or `npc_has_var`. `npc_add_var` can be used to store arbitrary local variables, and `u_add_var` can be used to store arbitrary "global" variables, and should be used in preference to setting effects. -`u_lose_var`, `npc_lose_var`: `var_name`, `type: type_str`, `context: context_str` | Your character or the NPC will clear any stored variable that has the same `var_name`, `type_str`, and `context_str`. -`u_adjust_var, npc_adjust_var`: `var_name, type: type_str`, `context: context_str`, `adjustment: adjustment_num` | Your character or the NPC will adjust the stored variable by `adjustment_num`. -`barber_hair` | Opens a menu allowing the player to choose a new hair style. -`barber_beard` | Opens a menu allowing the player to choose a new beard style. -`u_learn_recipe: recipe_string` | Your character will learn and memorize the recipe `recipe_string`. -`npc_first_topic: topic_string` | NPC permanently changes first dialogue topic to `topic_string`. +| Effect | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `u_add_effect: effect_string`, (_one of_ `duration: duration_string`, `duration: duration_int`)
`npc_add_effect: effect_string`, (_one of_ `duration: duration_string`, `duration: duration_int`) | Your character or the NPC will gain the effect for `duration_string` or `duration_int` turns. If `duration_string` is `"PERMANENT"`, the effect will be added permanently. | +| `u_add_trait: trait_string`
`npc_add_trait: trait_string` | Your character or the NPC will gain the trait. | +| `u_lose_effect: effect_string`
`npc_lose_effect: effect_string` | Your character or the NPC will lose the effect if they have it. | +| `u_lose_trait: trait_string`
`npc_lose_trait: trait_string` | Your character or the NPC will lose the trait. | +| `u_add_var, npc_add_var`: `var_name, type: type_str`, `context: context_str`, `value: value_str` | Your character or the NPC will store `value_str` as a variable that can be later retrieved by `u_has_var` or `npc_has_var`. `npc_add_var` can be used to store arbitrary local variables, and `u_add_var` can be used to store arbitrary "global" variables, and should be used in preference to setting effects. | +| `u_lose_var`, `npc_lose_var`: `var_name`, `type: type_str`, `context: context_str` | Your character or the NPC will clear any stored variable that has the same `var_name`, `type_str`, and `context_str`. | +| `u_adjust_var, npc_adjust_var`: `var_name, type: type_str`, `context: context_str`, `adjustment: adjustment_num` | Your character or the NPC will adjust the stored variable by `adjustment_num`. | +| `barber_hair` | Opens a menu allowing the player to choose a new hair style. | +| `barber_beard` | Opens a menu allowing the player to choose a new beard style. | +| `u_learn_recipe: recipe_string` | Your character will learn and memorize the recipe `recipe_string`. | +| `npc_first_topic: topic_string` | NPC permanently changes first dialogue topic to `topic_string`. | #### Trade / Items -Effect | Description ----|--- -`start_trade` | Opens the trade screen and allows trading with the NPC. -`buy_10_logs` | Places 10 logs in the ranch garage, and makes the NPC unavailable for 1 day. -`buy_100_logs` | Places 100 logs in the ranch garage, and makes the NPC unavailable for 7 days. -`give_equipment` | Allows your character to select items from the NPC's inventory and transfer them to your inventory. -`npc_gets_item` | Allows your character to select an item from your character's inventory and transfer it to the NPC's inventory. The NPC will not accept it if they do not have space or weight to carry it, and will set a reason that can be referenced in a future dynamic line with `"use_reason"`. -`npc_gets_item_to_use` | Allow your character to select an item from your character's inventory and transfer it to the NPC's inventory. The NPC will attempt to wield it and will not accept it if it is too heavy or is an inferior weapon to what they are currently using, and will set a reason that can be referenced in a future dynamic line with `"use_reason"`. -`u_buy_item: item_string`, (*optional* `cost: cost_num`, *optional* `count: count_num`, *optional* `container: container_string`) | The NPC will give your character the item or `count_num` copies of the item, contained in container, and will subtract `cost_num` from `op_of_u.owed` if specified. If the `op_o_u.owed` is less than `cost_num`, the trade window will open and the player will have to trade to make up the difference; the NPC will not give the player the item unless `cost_num` is satisfied.
If cost isn't present, the NPC gives your character the item at no charge. -`u_sell_item: item_string`, (*optional* `cost: cost_num`, *optional* `count: count_num`) | Your character will give the NPC the item or `count_num` copies of the item, and will add `cost_num` to the NPC's `op_of_u.owed` if specified.
If cost isn't present, the your character gives the NPC the item at no charge.
This effect will fail if you do not have at least `count_num` copies of the item, so it should be checked with `u_has_items`. -`u_bulk_trade_accept`
`npc_bulk_trade_accept` | Only valid after a `repeat_response`. The player trades all instances of the item from the `repeat_response` with the NPC. For `u_bulk_trade_accept`, the player loses the items from their inventory and gains the same value of the NPC's faction currecy; for `npc_bulk_trade_accept`, the player gains the items from the NPC's inventory and loses the same value of the NPC's faction currency. If there is remaining value, or the NPC doesn't have a faction currency, the remainder goes into the NPC's `op_of_u.owed`. -`u_bulk_donate`
`npc_bulk_donate` | Only valid after a `repeat_response`. The player or NPC transfers all instances of the item from the `repeat_response`. For `u_bulk_donate`, the player loses the items from their inventory and the NPC gains them; for `npc_bulk_donate`, the player gains the items from the NPC's inventory and the NPC loses them. -`u_spend_ecash: amount` | Remove `amount` from your character's pre-cataclysm bank account. Negative values means your character gains e-cash. NPCs should **not** deal in e-cash, only personal debts and items (including faction currency). -`add_debt: mod_list` | Increases the NPC's debt to the player by the values in the `mod_list`.
The following would increase the NPC's debt to the player by 1500x the NPC's altruism and 1000x the NPC's opinion of the player's value: `{ "effect": { "add_debt": [ [ "ALTRUISM", 3 ], [ "VALUE", 2 ], [ "TOTAL", 500 ] ] } }` -`u_consume_item`, `npc_consume_item: item_string`, (*optional* `count: count_num`) | You or the NPC will delete the item or `count_num` copies of the item from their inventory.
This effect will fail if the you or NPC does not have at least `count_num` copies of the item, so it should be checked with `u_has_items` or `npc_has_items`. -`u_remove_item_with`, `npc_remove_item_with: item_string` | You or the NPC will delete any instances of item in inventory.
This is an unconditional remove and will not fail if you or the NPC does not have the item. -`u_buy_monster: monster_type_string`, (*optional* `cost: cost_num`, *optional* `count: count_num`, *optional* `name: name_string`, *optional* `pacified: pacified_bool`) | The NPC will give your character `count_num` (default 1) instances of the monster as pets and will subtract `cost_num` from `op_of_u.owed` if specified. If the `op_o_u.owed` is less than `cost_num`, the trade window will open and the player will have to trade to make up the difference; the NPC will not give the player the item unless `cost_num` is satisfied.
If cost isn't present, the NPC gives your character the item at no charge.
If `name_string` is specified the monster(s) will have the specified name. If `pacified_bool` is set to true, the monster will have the pacified effect applied. - +| Effect | Description | +| ------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `start_trade` | Opens the trade screen and allows trading with the NPC. | +| `buy_10_logs` | Places 10 logs in the ranch garage, and makes the NPC unavailable for 1 day. | +| `buy_100_logs` | Places 100 logs in the ranch garage, and makes the NPC unavailable for 7 days. | +| `give_equipment` | Allows your character to select items from the NPC's inventory and transfer them to your inventory. | +| `npc_gets_item` | Allows your character to select an item from your character's inventory and transfer it to the NPC's inventory. The NPC will not accept it if they do not have space or weight to carry it, and will set a reason that can be referenced in a future dynamic line with `"use_reason"`. | +| `npc_gets_item_to_use` | Allow your character to select an item from your character's inventory and transfer it to the NPC's inventory. The NPC will attempt to wield it and will not accept it if it is too heavy or is an inferior weapon to what they are currently using, and will set a reason that can be referenced in a future dynamic line with `"use_reason"`. | +| `u_buy_item: item_string`, (_optional_ `cost: cost_num`, _optional_ `count: count_num`, _optional_ `container: container_string`) | The NPC will give your character the item or `count_num` copies of the item, contained in container, and will subtract `cost_num` from `op_of_u.owed` if specified. If the `op_o_u.owed` is less than `cost_num`, the trade window will open and the player will have to trade to make up the difference; the NPC will not give the player the item unless `cost_num` is satisfied.
If cost isn't present, the NPC gives your character the item at no charge. | +| `u_sell_item: item_string`, (_optional_ `cost: cost_num`, _optional_ `count: count_num`) | Your character will give the NPC the item or `count_num` copies of the item, and will add `cost_num` to the NPC's `op_of_u.owed` if specified.
If cost isn't present, the your character gives the NPC the item at no charge.
This effect will fail if you do not have at least `count_num` copies of the item, so it should be checked with `u_has_items`. | +| `u_bulk_trade_accept`
`npc_bulk_trade_accept` | Only valid after a `repeat_response`. The player trades all instances of the item from the `repeat_response` with the NPC. For `u_bulk_trade_accept`, the player loses the items from their inventory and gains the same value of the NPC's faction currecy; for `npc_bulk_trade_accept`, the player gains the items from the NPC's inventory and loses the same value of the NPC's faction currency. If there is remaining value, or the NPC doesn't have a faction currency, the remainder goes into the NPC's `op_of_u.owed`. | +| `u_bulk_donate`
`npc_bulk_donate` | Only valid after a `repeat_response`. The player or NPC transfers all instances of the item from the `repeat_response`. For `u_bulk_donate`, the player loses the items from their inventory and the NPC gains them; for `npc_bulk_donate`, the player gains the items from the NPC's inventory and the NPC loses them. | +| `u_spend_ecash: amount` | Remove `amount` from your character's pre-cataclysm bank account. Negative values means your character gains e-cash. NPCs should **not** deal in e-cash, only personal debts and items (including faction currency). | +| `add_debt: mod_list` | Increases the NPC's debt to the player by the values in the `mod_list`.
The following would increase the NPC's debt to the player by 1500x the NPC's altruism and 1000x the NPC's opinion of the player's value: `{ "effect": { "add_debt": [ [ "ALTRUISM", 3 ], [ "VALUE", 2 ], [ "TOTAL", 500 ] ] } }` | +| `u_consume_item`, `npc_consume_item: item_string`, (_optional_ `count: count_num`) | You or the NPC will delete the item or `count_num` copies of the item from their inventory.
This effect will fail if the you or NPC does not have at least `count_num` copies of the item, so it should be checked with `u_has_items` or `npc_has_items`. | +| `u_remove_item_with`, `npc_remove_item_with: item_string` | You or the NPC will delete any instances of item in inventory.
This is an unconditional remove and will not fail if you or the NPC does not have the item. | +| `u_buy_monster: monster_type_string`, (_optional_ `cost: cost_num`, _optional_ `count: count_num`, _optional_ `name: name_string`, _optional_ `pacified: pacified_bool`) | The NPC will give your character `count_num` (default 1) instances of the monster as pets and will subtract `cost_num` from `op_of_u.owed` if specified. If the `op_o_u.owed` is less than `cost_num`, the trade window will open and the player will have to trade to make up the difference; the NPC will not give the player the item unless `cost_num` is satisfied.
If cost isn't present, the NPC gives your character the item at no charge.
If `name_string` is specified the monster(s) will have the specified name. If `pacified_bool` is set to true, the monster will have the pacified effect applied. | #### Behavior / AI -Effect | Description ----|--- -`assign_guard` | Makes the NPC into a guard. If allied and at a camp, they will be assigned to that camp. -`stop_guard` | Releases the NPC from their guard duty (also see `assign_guard`). Friendly NPCs will return to following. -`start_camp` | The NPC will start a faction camp with the player. -`recover_camp` | Makes the NPC the overseer of an existing camp that doesn't have an overseer. -`remove_overseer` | Makes the NPC stop being an overseer, abandoning the faction camp. -`wake_up` | Wakes up sleeping, but not sedated, NPCs. -`reveal_stats` | Reveals the NPC's stats, based on the player's skill at assessing them. -`end_conversation` | Ends the conversation and makes the NPC ignore you from now on. -`insult_combat` | Ends the conversation and makes the NPC hostile, adds a message that character starts a fight with the NPC. -`hostile` | Makes the NPC hostile and ends the conversation. -`flee` | Makes the NPC flee from your character. -`follow` | Makes the NPC follow your character, joining the "Your Followers" faction. -`leave` | Makes the NPC leave the "Your Followers" faction and stop following your character. -`follow_only` | Makes the NPC follow your character without changing factions. -`stop_following` | Makes the NPC stop following your character without changing factions. -`npc_thankful` | Makes the NPC positively inclined toward your character. -`drop_weapon` | Makes the NPC drop their weapon. -`stranger_neutral` | Changes the NPC's attitude to neutral. -`start_mugging` | The NPC will approach your character and steal from your character, attacking if your character resists. -`lead_to_safety` | The NPC will gain the LEAD attitude and give your character the mission of reaching safety. -`start_training` | The NPC will train your character in a skill or martial art. -`companion_mission: role_string` | The NPC will offer you a list of missions for your allied NPCs, depending on the NPC's role. -`basecamp_mission` | The NPC will offer you a list of missions for your allied NPCs, depending on the local basecamp. -`bionic_install` | The NPC installs a bionic from your character's inventory onto your character, using very high skill, and charging you according to the operation's difficulty. -`bionic_remove` | The NPC removes a bionic from your character, using very high skill, and charging you according to the operation's difficulty. -`npc_class_change: class_string` | Change the NPC's faction to `class_string`. -`npc_faction_change: faction_string` | Change the NPC's faction membership to `faction_string`. -`u_faction_rep: rep_num` | Increases your reputation with the NPC's current faction, or decreases it if `rep_num` is negative. -`toggle_npc_rule: rule_string` | Toggles the value of a boolean NPC follower AI rule such as `"use_silent"` or `"allow_bash"` -`set_npc_rule: rule_string` | Sets the value of a boolean NPC follower AI rule such as `"use_silent"` or `"allow_bash"` -`clear_npc_rule: rule_string` | Clears the value of a boolean NPC follower AI rule such as `"use_silent"` or `"allow_bash"` -`set_npc_engagement_rule: rule_string` | Sets the NPC follower AI rule for engagement distance to the value of `rule_string`. -`set_npc_aim_rule: rule_string` | Sets the NPC follower AI rule for aiming speed to the value of `rule_string`. -`npc_die` | The NPC will die at the end of the conversation. +| Effect | Description | +| -------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `assign_guard` | Makes the NPC into a guard. If allied and at a camp, they will be assigned to that camp. | +| `stop_guard` | Releases the NPC from their guard duty (also see `assign_guard`). Friendly NPCs will return to following. | +| `start_camp` | The NPC will start a faction camp with the player. | +| `recover_camp` | Makes the NPC the overseer of an existing camp that doesn't have an overseer. | +| `remove_overseer` | Makes the NPC stop being an overseer, abandoning the faction camp. | +| `wake_up` | Wakes up sleeping, but not sedated, NPCs. | +| `reveal_stats` | Reveals the NPC's stats, based on the player's skill at assessing them. | +| `end_conversation` | Ends the conversation and makes the NPC ignore you from now on. | +| `insult_combat` | Ends the conversation and makes the NPC hostile, adds a message that character starts a fight with the NPC. | +| `hostile` | Makes the NPC hostile and ends the conversation. | +| `flee` | Makes the NPC flee from your character. | +| `follow` | Makes the NPC follow your character, joining the "Your Followers" faction. | +| `leave` | Makes the NPC leave the "Your Followers" faction and stop following your character. | +| `follow_only` | Makes the NPC follow your character without changing factions. | +| `stop_following` | Makes the NPC stop following your character without changing factions. | +| `npc_thankful` | Makes the NPC positively inclined toward your character. | +| `drop_weapon` | Makes the NPC drop their weapon. | +| `stranger_neutral` | Changes the NPC's attitude to neutral. | +| `start_mugging` | The NPC will approach your character and steal from your character, attacking if your character resists. | +| `lead_to_safety` | The NPC will gain the LEAD attitude and give your character the mission of reaching safety. | +| `start_training` | The NPC will train your character in a skill or martial art. | +| `companion_mission: role_string` | The NPC will offer you a list of missions for your allied NPCs, depending on the NPC's role. | +| `basecamp_mission` | The NPC will offer you a list of missions for your allied NPCs, depending on the local basecamp. | +| `bionic_install` | The NPC installs a bionic from your character's inventory onto your character, using very high skill, and charging you according to the operation's difficulty. | +| `bionic_remove` | The NPC removes a bionic from your character, using very high skill, and charging you according to the operation's difficulty. | +| `npc_class_change: class_string` | Change the NPC's faction to `class_string`. | +| `npc_faction_change: faction_string` | Change the NPC's faction membership to `faction_string`. | +| `u_faction_rep: rep_num` | Increases your reputation with the NPC's current faction, or decreases it if `rep_num` is negative. | +| `toggle_npc_rule: rule_string` | Toggles the value of a boolean NPC follower AI rule such as `"use_silent"` or `"allow_bash"` | +| `set_npc_rule: rule_string` | Sets the value of a boolean NPC follower AI rule such as `"use_silent"` or `"allow_bash"` | +| `clear_npc_rule: rule_string` | Clears the value of a boolean NPC follower AI rule such as `"use_silent"` or `"allow_bash"` | +| `set_npc_engagement_rule: rule_string` | Sets the NPC follower AI rule for engagement distance to the value of `rule_string`. | +| `set_npc_aim_rule: rule_string` | Sets the NPC follower AI rule for aiming speed to the value of `rule_string`. | +| `npc_die` | The NPC will die at the end of the conversation. | #### Map Updates -`mapgen_update: mapgen_update_id_string`
`mapgen_update:` *list of `mapgen_update_id_string`s*, (optional `assign_mission_target` parameters) | With no other parameters, updates the overmap tile at the player's current location with the changes described in `mapgen_update_id` (or for each `mapgen_update_id` in the list). The `assign_mission_target` parameters can be used to change the location of the overmap tile that gets updated. See [the missions docs](MISSIONS_JSON.md) for `assign_mission_target` parameters and [the mapgen docs](MAPGEN.md) for `mapgen_update`. + +`mapgen_update: mapgen_update_id_string`
`mapgen_update:` _list of `mapgen_update_id_string`s_, +(optional `assign_mission_target` parameters) | With no other parameters, updates the overmap tile +at the player's current location with the changes described in `mapgen_update_id` (or for each +`mapgen_update_id` in the list). The `assign_mission_target` parameters can be used to change the +location of the overmap tile that gets updated. See [the missions docs](MISSIONS_JSON.md) for +`assign_mission_target` parameters and [the mapgen docs](MAPGEN.md) for `mapgen_update`. #### Deprecated -Effect | Description ----|--- -`deny_follow`
`deny_lead`
`deny_train`
`deny_personal_info` | Sets the appropriate effect on the NPC for a few hours.
These are *deprecated* in favor of the more flexible `npc_add_effect` described above. +| Effect | Description | +| -------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------- | +| `deny_follow`
`deny_lead`
`deny_train`
`deny_personal_info` | Sets the appropriate effect on the NPC for a few hours.
These are _deprecated_ in favor of the more flexible `npc_add_effect` described above. | #### Sample effects + ```json { "topic": "TALK_EVAC_GUARD3_HOSTILE", "effect": [ { "u_faction_rep": -15 }, { "npc_change_faction": "hells_raiders" } ] } { "text": "Let's trade then.", "effect": "start_trade", "topic": "TALK_EVAC_MERCHANT" }, @@ -512,122 +650,138 @@ Effect | Description ``` --- + ### opinion changes + As a special effect, an NPC's opinion of your character can change. Use the following: #### opinion: { } -trust, value, fear, and anger are optional keywords inside the opinion object. Each keyword must be followed by a numeric value. The NPC's opinion is modified by the value. + +trust, value, fear, and anger are optional keywords inside the opinion object. Each keyword must be +followed by a numeric value. The NPC's opinion is modified by the value. #### Sample opinions + ```json { "effect": "follow", "opinion": { "trust": 1, "value": 1 }, "topic": "TALK_DONE" } { "topic": "TALK_DENY_FOLLOW", "effect": "deny_follow", "opinion": { "fear": -1, "value": -1, "anger": 1 } } ``` #### mission_opinion: { } -trust, value, fear, and anger are optional keywords inside the `mission_opinion` object. Each keyword must be followed by a numeric value. The NPC's opinion is modified by the value. + +trust, value, fear, and anger are optional keywords inside the `mission_opinion` object. Each +keyword must be followed by a numeric value. The NPC's opinion is modified by the value. --- ## Dialogue conditions -Conditions can be a simple string with no other values, a key and an int, a key and a string, a key and an array, or a key and an object. Arrays and objects can nest with each other and can contain any other condition. + +Conditions can be a simple string with no other values, a key and an int, a key and a string, a key +and an array, or a key and an object. Arrays and objects can nest with each other and can contain +any other condition. The following keys and simple strings are available: #### Boolean logic -Condition | Type | Description ---- | --- | --- -`"and"` | array | `true` if every condition in the array is true. Can be used to create complex condition tests, like `"[INTELLIGENCE 10+][PERCEPTION 12+] Your jacket is torn. Did you leave that scrap of fabric behind?"` -`"or"` | array | `true` if any condition in the array is true. Can be used to create complex condition tests, like `"[STRENGTH 9+] or [DEXTERITY 9+] I'm sure I can handle one zombie."` -`"not"` | object | `true` if the condition in the object or string is false. Can be used to create complex conditions test by negating other conditions, for text such as
`"[INTELLIGENCE 7-] Hitting the reactor with a hammer should shut it off safely, right?"` +| Condition | Type | Description | +| --------- | ------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `"and"` | array | `true` if every condition in the array is true. Can be used to create complex condition tests, like `"[INTELLIGENCE 10+][PERCEPTION 12+] Your jacket is torn. Did you leave that scrap of fabric behind?"` | +| `"or"` | array | `true` if any condition in the array is true. Can be used to create complex condition tests, like `"[STRENGTH 9+] or [DEXTERITY 9+] I'm sure I can handle one zombie."` | +| `"not"` | object | `true` if the condition in the object or string is false. Can be used to create complex conditions test by negating other conditions, for text such as
`"[INTELLIGENCE 7-] Hitting the reactor with a hammer should shut it off safely, right?"` | #### Player or NPC conditions -These conditions can be tested for the player using the `"u_"` form, and for the NPC using the `"npc_"` form. - -Condition | Type | Description ---- | --- | --- -`"u_male"`
`"npc_male"` | simple string | `true` if the player character or NPC is male. -`"u_female"`
`"npc_female"` | simple string | `true` if the player character or NPC is female. -`"u_at_om_location"`
`"npc_at_om_location"` | string | `true` if the player character or NPC is standing on an overmap tile with `u_at_om_location`'s id. The special string `"FACTION_CAMP_ANY"` changes it to return true if the player or NPC is standing on a faction camp overmap tile. The special string `"FACTION_CAMP_START"` changes it to return true if the overmap tile that the player or NPC is standing on can be turned into a faction camp overmap tile. -`"u_has_trait"`
`"npc_has_trait"` | string | `true` if the player character or NPC has a specific trait. Simpler versions of `u_has_any_trait` and `npc_has_any_trait` that only checks for one trait. -`"u_has_trait_flag"`
`"npc_has_trait_flag"` | string | `true` if the player character or NPC has any traits with the specific trait flag. More robust versions of `u_has_any_trait` and `npc_has_any_trait`. The special trait flag `"MUTATION_THRESHOLD"` checks to see if the player or NPC has crossed a mutation threshold. -`"u_has_any_trait"`
`"npc_has_any_trait"` | array | `true` if the player character or NPC has any trait or mutation in the array. Used to check multiple specific traits. -`"u_has_var"`, `"npc_has_var"` | string | `"type": type_str`, `"context": context_str`, and `"value": value_str` are required fields in the same dictionary as `"u_has_var"` or `"npc_has_var"`.
`true` is the player character or NPC has a variable set by `"u_add_var"` or `"npc_add_var"` with the string, `type_str`, `context_str`, and `value_str`. -`"u_compare_var"`, `"npc_compare_var"` | dictionary | `"type": type_str`, `"context": context_str`, `"op": op_str`, `"value": value_num` are required fields, referencing a var as in `"u_add_var"` or `"npc_add_var"`.
`true` if the player character or NPC has a stored variable that is true for the provided operator `op_str` (one of `==`, `!=`, `<`, `>`, `<=`, `>=`) and value. -`"u_has_strength"`
`"npc_has_strength"` | int | `true` if the player character's or NPC's strength is at least the value of `u_has_strength` or `npc_has_strength`. -`"u_has_dexterity"`
`"npc_has_dexterity"` | int | `true` if the player character's or NPC's dexterity is at least the value of `u_has_dexterity` or `npc_has_dexterity`. -`"u_has_intelligence"`
`"npc_has_intelligence"` | int | `true` if the player character's or NPC's intelligence is at least the value of `u_has_intelligence` or `npc_has_intelligence`. -`"u_has_perception"`
`"npc_has_perception"` | int | `true` if the player character's or NPC's perception is at least the value of `u_has_perception` or `npc_has_perception`. -`"u_has_item"`
`"npc_has_item"` | string | `true` if the player character or NPC has something with `u_has_item`'s or `npc_has_item`'s `item_id` in their inventory. -`"u_has_items"`
`"npc_has_item"` | dictionary | `u_has_items` or `npc_has_items` must be a dictionary with an `item` string and a `count` int.
`true` if the player character or NPC has at least `count` charges or counts of `item` in their inventory. -`"u_has_item_category"`
`"npc_has_item_category"` | string | `"count": item_count` is an optional field that must be in the same dictionary and defaults to 1 if not specified. `true` if the player or NPC has `item_count` items with the same category as `u_has_item_category` or `npc_has_item_category`. -`"u_has_bionics"`
`"npc_has_bionics"` | string | `true` if the player or NPC has an installed bionic with an `bionic_id` matching `"u_has_bionics"` or `"npc_has_bionics"`. The special string "ANY" returns true if the player or NPC has any installed bionics. -`"u_has_effect"`
`"npc_has_effect"` | string | `true` if the player character or NPC is under the effect with `u_has_effect` or `npc_has_effect`'s `effect_id`. -`"u_can_stow_weapon"`
`"npc_can_stow_weapon"` | simple string | `true` if the player character or NPC is wielding a weapon and has enough space to put it away. -`"u_has_weapon"`
`"npc_has_weapon"` | simple string | `true` if the player character or NPC is wielding a weapon. -`"u_driving"`
`"npc_driving"` | simple string | `true` if the player character or NPC is operating a vehicle. Note NPCs cannot currently operate vehicles. -`"u_has_skill"`
`"npc_has_skill"` | dictionary | `u_has_skill` or `npc_has_skill` must be a dictionary with a `skill` string and a `level` int.
`true` if the player character or NPC has at least the value of `level` in `skill`. -`"u_know_recipe"` | string | `true` if the player character knows the recipe specified in `u_know_recipe`. It only counts as known if it is actually memorized--holding a book with the recipe in it will not count. + +These conditions can be tested for the player using the `"u_"` form, and for the NPC using the +`"npc_"` form. + +| Condition | Type | Description | +| ------------------------------------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `"u_male"`
`"npc_male"` | simple string | `true` if the player character or NPC is male. | +| `"u_female"`
`"npc_female"` | simple string | `true` if the player character or NPC is female. | +| `"u_at_om_location"`
`"npc_at_om_location"` | string | `true` if the player character or NPC is standing on an overmap tile with `u_at_om_location`'s id. The special string `"FACTION_CAMP_ANY"` changes it to return true if the player or NPC is standing on a faction camp overmap tile. The special string `"FACTION_CAMP_START"` changes it to return true if the overmap tile that the player or NPC is standing on can be turned into a faction camp overmap tile. | +| `"u_has_trait"`
`"npc_has_trait"` | string | `true` if the player character or NPC has a specific trait. Simpler versions of `u_has_any_trait` and `npc_has_any_trait` that only checks for one trait. | +| `"u_has_trait_flag"`
`"npc_has_trait_flag"` | string | `true` if the player character or NPC has any traits with the specific trait flag. More robust versions of `u_has_any_trait` and `npc_has_any_trait`. The special trait flag `"MUTATION_THRESHOLD"` checks to see if the player or NPC has crossed a mutation threshold. | +| `"u_has_any_trait"`
`"npc_has_any_trait"` | array | `true` if the player character or NPC has any trait or mutation in the array. Used to check multiple specific traits. | +| `"u_has_var"`, `"npc_has_var"` | string | `"type": type_str`, `"context": context_str`, and `"value": value_str` are required fields in the same dictionary as `"u_has_var"` or `"npc_has_var"`.
`true` is the player character or NPC has a variable set by `"u_add_var"` or `"npc_add_var"` with the string, `type_str`, `context_str`, and `value_str`. | +| `"u_compare_var"`, `"npc_compare_var"` | dictionary | `"type": type_str`, `"context": context_str`, `"op": op_str`, `"value": value_num` are required fields, referencing a var as in `"u_add_var"` or `"npc_add_var"`.
`true` if the player character or NPC has a stored variable that is true for the provided operator `op_str` (one of `==`, `!=`, `<`, `>`, `<=`, `>=`) and value. | +| `"u_has_strength"`
`"npc_has_strength"` | int | `true` if the player character's or NPC's strength is at least the value of `u_has_strength` or `npc_has_strength`. | +| `"u_has_dexterity"`
`"npc_has_dexterity"` | int | `true` if the player character's or NPC's dexterity is at least the value of `u_has_dexterity` or `npc_has_dexterity`. | +| `"u_has_intelligence"`
`"npc_has_intelligence"` | int | `true` if the player character's or NPC's intelligence is at least the value of `u_has_intelligence` or `npc_has_intelligence`. | +| `"u_has_perception"`
`"npc_has_perception"` | int | `true` if the player character's or NPC's perception is at least the value of `u_has_perception` or `npc_has_perception`. | +| `"u_has_item"`
`"npc_has_item"` | string | `true` if the player character or NPC has something with `u_has_item`'s or `npc_has_item`'s `item_id` in their inventory. | +| `"u_has_items"`
`"npc_has_item"` | dictionary | `u_has_items` or `npc_has_items` must be a dictionary with an `item` string and a `count` int.
`true` if the player character or NPC has at least `count` charges or counts of `item` in their inventory. | +| `"u_has_item_category"`
`"npc_has_item_category"` | string | `"count": item_count` is an optional field that must be in the same dictionary and defaults to 1 if not specified. `true` if the player or NPC has `item_count` items with the same category as `u_has_item_category` or `npc_has_item_category`. | +| `"u_has_bionics"`
`"npc_has_bionics"` | string | `true` if the player or NPC has an installed bionic with an `bionic_id` matching `"u_has_bionics"` or `"npc_has_bionics"`. The special string "ANY" returns true if the player or NPC has any installed bionics. | +| `"u_has_effect"`
`"npc_has_effect"` | string | `true` if the player character or NPC is under the effect with `u_has_effect` or `npc_has_effect`'s `effect_id`. | +| `"u_can_stow_weapon"`
`"npc_can_stow_weapon"` | simple string | `true` if the player character or NPC is wielding a weapon and has enough space to put it away. | +| `"u_has_weapon"`
`"npc_has_weapon"` | simple string | `true` if the player character or NPC is wielding a weapon. | +| `"u_driving"`
`"npc_driving"` | simple string | `true` if the player character or NPC is operating a vehicle. Note NPCs cannot currently operate vehicles. | +| `"u_has_skill"`
`"npc_has_skill"` | dictionary | `u_has_skill` or `npc_has_skill` must be a dictionary with a `skill` string and a `level` int.
`true` if the player character or NPC has at least the value of `level` in `skill`. | +| `"u_know_recipe"` | string | `true` if the player character knows the recipe specified in `u_know_recipe`. It only counts as known if it is actually memorized--holding a book with the recipe in it will not count. | #### Player Only conditions `"u_has_mission"` | string | `true` if the mission is assigned to the player character. -`"u_has_ecash"` | int | `true` if the player character has at least `u_has_ecash` ecash available in his pre-cataclysm bank account. NPCs should **not** deal in e-cash, only personal debts and items (including faction currency). -`"u_are_owed"` | int | `true` if the NPC's op_of_u.owed is at least `u_are_owed`. Can be used to check if the player can buy something from the NPC without needing to barter anything. -`"u_has_camp"` | simple string | `true` is the player has one or more active base camps. +`"u_has_ecash"` | int | `true` if the player character has at least `u_has_ecash` ecash available in +his pre-cataclysm bank account. NPCs should **not** deal in e-cash, only personal debts and items +(including faction currency). `"u_are_owed"` | int | `true` if the NPC's op_of_u.owed is at least +`u_are_owed`. Can be used to check if the player can buy something from the NPC without needing to +barter anything. `"u_has_camp"` | simple string | `true` is the player has one or more active base +camps. #### Player and NPC interaction conditions -Condition | Type | Description ---- | --- | --- -`"at_safe_space"` | simple string | `true` if the NPC's current overmap location passes the `is_safe()` test. -`"has_assigned_mission"` | simple string | `true` if the player character has exactly one mission from the NPC. Can be used for texts like "About that job...". -`"has_many_assigned_missions"` | simple string | `true` if the player character has several mission from the NPC (more than one). Can be used for texts like "About one of those jobs..." and to switch to the `"TALK_MISSION_LIST_ASSIGNED"` topic. -`"has_no_available_mission"` | simple string | `true` if the NPC has no jobs available for the player character. -`"has_available_mission"` | simple string | `true` if the NPC has one job available for the player character. -`"has_many_available_missions"` | simple string | `true` if the NPC has several jobs available for the player character. -`"mission_goal"` | string | `true` if the NPC's current mission has the same goal as `mission_goal`. -`"mission_complete"` | simple string | `true` if the player has completed the NPC's current mission. -`"mission_incomplete"` | simple string | `true` if the player hasn't completed the NPC's current mission. -`"mission_has_generic_rewards"` | simple string | `true` if the NPC's current mission is flagged as having generic rewards. -`"npc_service"` | simple string | `true` if the NPC does not have the `"currently_busy"` effect. Useful to check if the player character can hire an NPC to perform a task that would take time to complete. Functionally, this is identical to `not": { "npc_has_effect": "currently_busy" }`. Same as `npc_available`. -`"npc_allies"` | int | `true` if the player character has at least `npc_allies` number of NPC allies. -`"npc_following"` | simple string | `true` if the NPC is following the player character. -`"is_by_radio"` | simple string | `true` if the player is talking to the NPC over a radio. +| Condition | Type | Description | +| ------------------------------- | ------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `"at_safe_space"` | simple string | `true` if the NPC's current overmap location passes the `is_safe()` test. | +| `"has_assigned_mission"` | simple string | `true` if the player character has exactly one mission from the NPC. Can be used for texts like "About that job...". | +| `"has_many_assigned_missions"` | simple string | `true` if the player character has several mission from the NPC (more than one). Can be used for texts like "About one of those jobs..." and to switch to the `"TALK_MISSION_LIST_ASSIGNED"` topic. | +| `"has_no_available_mission"` | simple string | `true` if the NPC has no jobs available for the player character. | +| `"has_available_mission"` | simple string | `true` if the NPC has one job available for the player character. | +| `"has_many_available_missions"` | simple string | `true` if the NPC has several jobs available for the player character. | +| `"mission_goal"` | string | `true` if the NPC's current mission has the same goal as `mission_goal`. | +| `"mission_complete"` | simple string | `true` if the player has completed the NPC's current mission. | +| `"mission_incomplete"` | simple string | `true` if the player hasn't completed the NPC's current mission. | +| `"mission_has_generic_rewards"` | simple string | `true` if the NPC's current mission is flagged as having generic rewards. | +| `"npc_service"` | simple string | `true` if the NPC does not have the `"currently_busy"` effect. Useful to check if the player character can hire an NPC to perform a task that would take time to complete. Functionally, this is identical to `not": { "npc_has_effect": "currently_busy" }`. Same as `npc_available`. | +| `"npc_allies"` | int | `true` if the player character has at least `npc_allies` number of NPC allies. | +| `"npc_following"` | simple string | `true` if the NPC is following the player character. | +| `"is_by_radio"` | simple string | `true` if the player is talking to the NPC over a radio. | #### NPC only conditions -Condition | Type | Description ---- | --- | --- -`"npc_available"` | simple string | `true` if the NPC does not have effect `"currently_busy"`. -`"npc_following"` | simple string | `true` if the NPC is following the player character. -`"npc_friend"` | simple string | `true` if the NPC is friendly to the player character. -`"npc_hostile"` | simple string | `true` if the NPC is an enemy of the player character. -`"npc_train_skills"` | simple string | `true` if the NPC has one or more skills with more levels than the player. -`"npc_train_styles"` | simple string | `true` if the NPC knows one or more martial arts styles that the player does not know. -`"npc_has_class"` | array | `true` if the NPC is a member of an NPC class. -`"npc_role_nearby"` | string | `true` if there is an NPC with the same companion mission role as `npc_role_nearby` within 100 tiles. -`"has_reason"` | simple string | `true` if a previous effect set a reason for why an effect could not be completed. +| Condition | Type | Description | +| -------------------- | ------------- | ----------------------------------------------------------------------------------------------------- | +| `"npc_available"` | simple string | `true` if the NPC does not have effect `"currently_busy"`. | +| `"npc_following"` | simple string | `true` if the NPC is following the player character. | +| `"npc_friend"` | simple string | `true` if the NPC is friendly to the player character. | +| `"npc_hostile"` | simple string | `true` if the NPC is an enemy of the player character. | +| `"npc_train_skills"` | simple string | `true` if the NPC has one or more skills with more levels than the player. | +| `"npc_train_styles"` | simple string | `true` if the NPC knows one or more martial arts styles that the player does not know. | +| `"npc_has_class"` | array | `true` if the NPC is a member of an NPC class. | +| `"npc_role_nearby"` | string | `true` if there is an NPC with the same companion mission role as `npc_role_nearby` within 100 tiles. | +| `"has_reason"` | simple string | `true` if a previous effect set a reason for why an effect could not be completed. | #### NPC Follower AI rules -Condition | Type | Description ---- | --- | --- -`"npc_aim_rule"` | string | `true` if the NPC follower AI rule for aiming matches the string. -`"npc_engagement_rule"` | string | `true` if the NPC follower AI rule for engagement matches the string. -`"npc_rule"` | string | `true` if the NPC follower AI rule for that matches string is set. -#### Environment +| Condition | Type | Description | +| ----------------------- | ------ | --------------------------------------------------------------------- | +| `"npc_aim_rule"` | string | `true` if the NPC follower AI rule for aiming matches the string. | +| `"npc_engagement_rule"` | string | `true` if the NPC follower AI rule for engagement matches the string. | +| `"npc_rule"` | string | `true` if the NPC follower AI rule for that matches string is set. | -Condition | Type | Description ---- | --- | --- -`"days_since_cataclysm"` | int | `true` if at least `days_since_cataclysm` days have passed since the Cataclysm. -`"is_season"` | string | `true` if the current season matches `is_season`, which must be one of "`spring"`, `"summer"`, `"autumn"`, or `"winter"`. -`"is_day"` | simple string | `true` if it is currently daytime. -`"is_outside"` | simple string | `true` if the NPC is on a tile without a roof. +#### Environment +| Condition | Type | Description | +| ------------------------ | ------------- | ------------------------------------------------------------------------------------------------------------------------- | +| `"days_since_cataclysm"` | int | `true` if at least `days_since_cataclysm` days have passed since the Cataclysm. | +| `"is_season"` | string | `true` if the current season matches `is_season`, which must be one of "`spring"`, `"summer"`, `"autumn"`, or `"winter"`. | +| `"is_day"` | simple string | `true` if it is currently daytime. | +| `"is_outside"` | simple string | `true` if the NPC is on a tile without a roof. | #### Sample responses with conditions and effects + ```json { "text": "Understood. I'll get those antibiotics.", diff --git a/doc/OVERMAP.md b/doc/OVERMAP.md index fb436d74f9ee..2d05939bb3db 100644 --- a/doc/OVERMAP.md +++ b/doc/OVERMAP.md @@ -34,16 +34,16 @@ player directly interacts with, providing the necessary context for local map ge By example, the overmap tells the game: -* where the cities are -* where the roads are -* where the buildings are -* what types the buildings are +- where the cities are +- where the roads are +- where the buildings are +- what types the buildings are but it does not tell the game: -* what the actual road terrain looks like -* what the actual building layout looks like -* what items are in the building +- what the actual road terrain looks like +- what the actual building layout looks like +- what items are in the building It can sometimes be useful to think of the overmap as the outline for the game world which will then be filled in as the player explores. The rest of this document is a discussion of how we can create @@ -51,14 +51,14 @@ that outline. ## Terminology and Types -First we need to briefly discuss some of the data types used by the -overmap. +First we need to briefly discuss some of the data types used by the overmap. ### overmap_terrain -The fundamental unit of the overmap is the **overmap_terrain**, which defines the id, name, symbol, color -(and more, but we'll get to that) used to represent a single location on the overmap. The overmap is 180 -overmap terrains wide, 180 overmap terrains tall, and 21 overmap terrains deep (these are the z-levels). +The fundamental unit of the overmap is the **overmap_terrain**, which defines the id, name, symbol, +color (and more, but we'll get to that) used to represent a single location on the overmap. The +overmap is 180 overmap terrains wide, 180 overmap terrains tall, and 21 overmap terrains deep (these +are the z-levels). In this example snippet of an overmap, each character corresponds one entry in the overmap which references a given overmap terrain: @@ -76,11 +76,11 @@ So for example, the `F` is a forest which has a definition like this: ```json { - "type": "overmap_terrain", - "id": "forest", - "name": "forest", - "sym": "F", - "color": "green" + "type": "overmap_terrain", + "id": "forest", + "name": "forest", + "sym": "F", + "color": "green" } ``` @@ -88,53 +88,55 @@ and the `^` is a house which has a definition like this: ```json { - "type": "overmap_terrain", - "id": "house", - "name": "house", - "sym": "^", - "color": "light_green" + "type": "overmap_terrain", + "id": "house", + "name": "house", + "sym": "^", + "color": "light_green" } ``` -It's important to note that a single overmap terrain definition is referenced for every usage of that -overmap terrain in the overmap--if we were to change the color of our forest from `green` to `red`, every -forest in the overmap would be red. +It's important to note that a single overmap terrain definition is referenced for every usage of +that overmap terrain in the overmap--if we were to change the color of our forest from `green` to +`red`, every forest in the overmap would be red. ### overmap_special / city_building -The next important concept for the overmap is that of the **overmap_special** and -**city_building**. These types, which are similar in structure, are the mechanism by which multiple -overmap terrains can be collected together into one conceptual entity for placement on the overmap. -If you wanted to have a sprawling mansion, a two story house, a large pond, or a secret lair placed -under an unassuming bookstore, you would need to use an **overmap_special** or a **city_building**. +The next important concept for the overmap is that of the **overmap_special** and **city_building**. +These types, which are similar in structure, are the mechanism by which multiple overmap terrains +can be collected together into one conceptual entity for placement on the overmap. If you wanted to +have a sprawling mansion, a two story house, a large pond, or a secret lair placed under an +unassuming bookstore, you would need to use an **overmap_special** or a **city_building**. -These types are effectively a list of the overmap terrains that compose them, the placement of -those overmap terrains relative to each other, and some data used to drive the placement of the -overmap special / city building (e.g. how far from a city, should be it connected to a road, can it -be placed in a forest/field/river, etc). +These types are effectively a list of the overmap terrains that compose them, the placement of those +overmap terrains relative to each other, and some data used to drive the placement of the overmap +special / city building (e.g. how far from a city, should be it connected to a road, can it be +placed in a forest/field/river, etc). ### overmap_connection -Speaking of roads, the concept of linear features like roads, sewers, subways, railroads, and -forest trails are managed through a combination of overmap terrain attributes and another type -called an **overmap_connection**. +Speaking of roads, the concept of linear features like roads, sewers, subways, railroads, and forest +trails are managed through a combination of overmap terrain attributes and another type called an +**overmap_connection**. An overmap connection effectively defines the types of overmap terrain on which a given connection can be made, the "cost" to make that connection, and the type of terrain to be placed when making the connection. This, for example, is what allows us to say that: -* a road may be placed on fields, forests, swamps and rivers -* fields are preferred over forests, which are preferred over swamps, which are preferred over rivers -* a road crossing a river will be a bridge +- a road may be placed on fields, forests, swamps and rivers +- fields are preferred over forests, which are preferred over swamps, which are preferred over + rivers +- a road crossing a river will be a bridge -The **overmap_connection** data will then be used to create a linear road feature connecting two points, -applying the previously defined rules. +The **overmap_connection** data will then be used to create a linear road feature connecting two +points, applying the previously defined rules. ### overmap_location -We've previously mentioned defining valid overmap terrain types for the placement of overmap specials, -city buildings, and overmap connections, but one thing to clarify is these actually leverage another -type called an **overmap_location** rather than referencing **overmap_terrain** values directly. +We've previously mentioned defining valid overmap terrain types for the placement of overmap +specials, city buildings, and overmap connections, but one thing to clarify is these actually +leverage another type called an **overmap_location** rather than referencing **overmap_terrain** +values directly. Simply put, an **overmap_location** is just a named collection of **overmap_terrain** values. @@ -179,69 +181,69 @@ update these definitions as follows: ### Rotation -If an overmap terrain can be rotated (i.e. it does not have the `NO_ROTATE` flag), then when -the game loads the definition from JSON, it will create the rotated definitions automatically, -suffixing the `id` defined here with `_north`, `_east`, `_south` or `_west`. This will be -particularly relevant if the overmap terrains are used in **overmap_special** or **city_building** -definitions, because if those are allowed to rotate, it's desirable to specify a particular -rotation for the referenced overmap terrains (e.g. the `_north` version for all). +If an overmap terrain can be rotated (i.e. it does not have the `NO_ROTATE` flag), then when the +game loads the definition from JSON, it will create the rotated definitions automatically, suffixing +the `id` defined here with `_north`, `_east`, `_south` or `_west`. This will be particularly +relevant if the overmap terrains are used in **overmap_special** or **city_building** definitions, +because if those are allowed to rotate, it's desirable to specify a particular rotation for the +referenced overmap terrains (e.g. the `_north` version for all). ### Fields -| Identifier | Description | -| ----------------- | ------------------------------------------------------------------------------------------------ | -| `type` | Must be "overmap_terrain". | -| `id` | Unique id. | -| `name` | Name for the location shown in game. | -| `sym` | Symbol used when drawing the location, like `"F"` (or you may use an ASCII value like `70`). | -| `color` | Color to draw the symbol in. See [COLOR.md](COLOR.md). | -| `looks_like` | Id of another overmap terrain to be used for the graphical tile, if this doesn't have one. | -| `connect_group` | Specify that this overmap terrain might be graphically connected to its neighbours, should a tileset wish to. It will connect to any other `overmap_terrain` with the same `connect_group`. | -| `see_cost` | Affects player vision on overmap. Higher values obstruct vision more. | -| `travel_cost` | Affects pathfinding cost. Higher values are harder to travel through (reference: Forest = 10 ) | -| `extras` | Reference to a named `map_extras` in region_settings, defines which map extras can be applied. | -| `mondensity` | Summed with values for adjacent overmap terrains to influence density of monsters spawned here. | -| `spawns` | Spawns added once at mapgen. Monster group, % chance, population range (min/max). | -| `flags` | See `Overmap terrains` in [JSON_FLAGS.md](JSON_FLAGS.md). | -| `mapgen` | Specify a C++ mapgen function. Don't do this--use JSON. | -| `mapgen_straight` | Specify a C++ mapgen function for a LINEAR feature variation. | -| `mapgen_curved` | Specify a C++ mapgen function for a LINEAR feature variation. | -| `mapgen_end` | Specify a C++ mapgen function for a LINEAR feature variation. | -| `mapgen_tee` | Specify a C++ mapgen function for a LINEAR feature variation. | -| `mapgen_four_way` | Specify a C++ mapgen function for a LINEAR feature variation. | +| Identifier | Description | +| ----------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `type` | Must be "overmap_terrain". | +| `id` | Unique id. | +| `name` | Name for the location shown in game. | +| `sym` | Symbol used when drawing the location, like `"F"` (or you may use an ASCII value like `70`). | +| `color` | Color to draw the symbol in. See [COLOR.md](COLOR.md). | +| `looks_like` | Id of another overmap terrain to be used for the graphical tile, if this doesn't have one. | +| `connect_group` | Specify that this overmap terrain might be graphically connected to its neighbours, should a tileset wish to. It will connect to any other `overmap_terrain` with the same `connect_group`. | +| `see_cost` | Affects player vision on overmap. Higher values obstruct vision more. | +| `travel_cost` | Affects pathfinding cost. Higher values are harder to travel through (reference: Forest = 10 ) | +| `extras` | Reference to a named `map_extras` in region_settings, defines which map extras can be applied. | +| `mondensity` | Summed with values for adjacent overmap terrains to influence density of monsters spawned here. | +| `spawns` | Spawns added once at mapgen. Monster group, % chance, population range (min/max). | +| `flags` | See `Overmap terrains` in [JSON_FLAGS.md](JSON_FLAGS.md). | +| `mapgen` | Specify a C++ mapgen function. Don't do this--use JSON. | +| `mapgen_straight` | Specify a C++ mapgen function for a LINEAR feature variation. | +| `mapgen_curved` | Specify a C++ mapgen function for a LINEAR feature variation. | +| `mapgen_end` | Specify a C++ mapgen function for a LINEAR feature variation. | +| `mapgen_tee` | Specify a C++ mapgen function for a LINEAR feature variation. | +| `mapgen_four_way` | Specify a C++ mapgen function for a LINEAR feature variation. | ### Example -A real `overmap_terrain` wouldn't have all these defined at the same time, but in the interest of -an exhaustive example... +A real `overmap_terrain` wouldn't have all these defined at the same time, but in the interest of an +exhaustive example... ```json { - "type": "overmap_terrain", - "id": "field", - "name": "field", - "sym": ".", - "color": "brown", - "looks_like": "forest", - "see_cost": 2, - "extras": "field", - "mondensity": 2, - "spawns": { "group": "GROUP_FOREST", "population": [ 0, 1 ], "chance": 13 }, - "flags": [ "NO_ROTATE" ], - "mapgen": [ { "method": "builtin", "name": "bridge" } ], - "mapgen_straight": [ { "method": "builtin", "name": "road_straight" } ], - "mapgen_curved": [ { "method": "builtin", "name": "road_curved" } ], - "mapgen_end": [ { "method": "builtin", "name": "road_end" } ], - "mapgen_tee": [ { "method": "builtin", "name": "road_tee" } ], - "mapgen_four_way": [ { "method": "builtin", "name": "road_four_way" } ] + "type": "overmap_terrain", + "id": "field", + "name": "field", + "sym": ".", + "color": "brown", + "looks_like": "forest", + "see_cost": 2, + "extras": "field", + "mondensity": 2, + "spawns": { "group": "GROUP_FOREST", "population": [0, 1], "chance": 13 }, + "flags": ["NO_ROTATE"], + "mapgen": [{ "method": "builtin", "name": "bridge" }], + "mapgen_straight": [{ "method": "builtin", "name": "road_straight" }], + "mapgen_curved": [{ "method": "builtin", "name": "road_curved" }], + "mapgen_end": [{ "method": "builtin", "name": "road_end" }], + "mapgen_tee": [{ "method": "builtin", "name": "road_tee" }], + "mapgen_four_way": [{ "method": "builtin", "name": "road_four_way" }] } ``` ## Overmap Special An overmap special is an entity that is placed in the overmap after the city generation process has -completed--they are the "non-city" counterpart to the **city_building** type. They commonly are -made up of multiple overmap terrains (though not always), may have overmap connections (e.g. roads, +completed--they are the "non-city" counterpart to the **city_building** type. They commonly are made +up of multiple overmap terrains (though not always), may have overmap connections (e.g. roads, sewers, subways), and have JSON-defined rules guiding their placement. ### Mandatory Overmap Specials @@ -260,9 +262,9 @@ minimum should be 0. In general, it is desirable to define your overmap special as allowing rotation--this will provide variety in the game world and allow for more possible valid locations when attempting to place the overmap special. A consequence of the relationship between rotating an overmap special and rotating -the underlying overmap terrains that make up the special is that the overmap special should reference -a specific rotated version of the associated overmap terrain--generally, this is the `_north` rotation -as it corresponds to the way in which the JSON for mapgen is defined. +the underlying overmap terrains that make up the special is that the overmap special should +reference a specific rotated version of the associated overmap terrain--generally, this is the +`_north` rotation as it corresponds to the way in which the JSON for mapgen is defined. ### Locations @@ -276,7 +278,7 @@ level value and then only specify it for individual entries that differ. ### Fields -| Identifier | Description | +| Identifier | Description | | --------------- | ----------------------------------------------------------------------------------------------------- | | `type` | Must be "overmap_special". | | `id` | Unique id. | @@ -297,25 +299,25 @@ level value and then only specify it for individual entries that differ. "type": "overmap_special", "id": "campground", "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "campground_1a_north", "locations": [ "forest_edge" ] }, - { "point": [ 1, 0, 0 ], "overmap": "campground_1b_north" }, - { "point": [ 0, 1, 0 ], "overmap": "campground_2a_north" }, - { "point": [ 1, 1, 0 ], "overmap": "campground_2b_north" } + { "point": [0, 0, 0], "overmap": "campground_1a_north", "locations": ["forest_edge"] }, + { "point": [1, 0, 0], "overmap": "campground_1b_north" }, + { "point": [0, 1, 0], "overmap": "campground_2a_north" }, + { "point": [1, 1, 0], "overmap": "campground_2b_north" } ], - "connections": [ { "point": [ 1, -1, 0 ], "connection": "local_road", "from": [ 1, 0, 0 ] } ], - "locations": [ "forest" ], - "city_distance": [ 10, -1 ], - "city_sizes": [ 3, 12 ], - "occurrences": [ 0, 5 ], - "flags": [ "CLASSIC" ], - "rotate" : true + "connections": [{ "point": [1, -1, 0], "connection": "local_road", "from": [1, 0, 0] }], + "locations": ["forest"], + "city_distance": [10, -1], + "city_sizes": [3, 12], + "occurrences": [0, 5], + "flags": ["CLASSIC"], + "rotate": true } ] ``` ### Overmaps -| Identifier | Description | +| Identifier | Description | | ----------- | -------------------------------------------------------------------------- | | `point` | `[ x, y, z]` of the overmap terrain within the special. | | `overmap` | Id of the `overmap_terrain` to place at the location. | @@ -323,7 +325,7 @@ level value and then only specify it for individual entries that differ. ### Connections -| Identifier | Description | +| Identifier | Description | | ------------ | -------------------------------------------------------------------------------------------------- | | `point` | `[ x, y, z]` of the connection end point. Cannot overlap an overmap terrain entry for the special. | | `connection` | Id of the `overmap_connection` to build. | @@ -332,19 +334,19 @@ level value and then only specify it for individual entries that differ. ## City Building A city building is an entity that is placed in the overmap during the city generation process--they -are the "city" counterpart to the **overmap_special** type. The definition for a city building is a subset -of that for an overmap special, and consequently will not be repeated in detail here. +are the "city" counterpart to the **overmap_special** type. The definition for a city building is a +subset of that for an overmap special, and consequently will not be repeated in detail here. ### Mandatory Overmap Specials / Region Settings -City buildings are not subject to the same quantity limitations as overmap specials, and in fact -the occurrences attribute does not apply at all. Instead, the placement of city buildings is driven -by the frequency assigned to the city building within the `region_settings`. Consult +City buildings are not subject to the same quantity limitations as overmap specials, and in fact the +occurrences attribute does not apply at all. Instead, the placement of city buildings is driven by +the frequency assigned to the city building within the `region_settings`. Consult [REGION_SETTINGS.md](REGION_SETTINGS.md) for more details. ### Fields -| Identifier | Description | +| Identifier | Description | | ----------- | -------------------------------------------------------------------------------- | | `type` | Must be "city_building". | | `id` | Unique id. | @@ -360,20 +362,20 @@ by the frequency assigned to the city building within the `region_settings`. Con { "type": "city_building", "id": "zoo", - "locations": [ "land" ], + "locations": ["land"], "overmaps": [ - { "point": [ 0, 0, 0 ], "overmap": "zoo_0_0_north" }, - { "point": [ 1, 0, 0 ], "overmap": "zoo_1_0_north" }, - { "point": [ 2, 0, 0 ], "overmap": "zoo_2_0_north" }, - { "point": [ 0, 1, 0 ], "overmap": "zoo_0_1_north" }, - { "point": [ 1, 1, 0 ], "overmap": "zoo_1_1_north" }, - { "point": [ 2, 1, 0 ], "overmap": "zoo_2_1_north" }, - { "point": [ 0, 2, 0 ], "overmap": "zoo_0_2_north" }, - { "point": [ 1, 2, 0 ], "overmap": "zoo_1_2_north" }, - { "point": [ 2, 2, 0 ], "overmap": "zoo_2_2_north" } + { "point": [0, 0, 0], "overmap": "zoo_0_0_north" }, + { "point": [1, 0, 0], "overmap": "zoo_1_0_north" }, + { "point": [2, 0, 0], "overmap": "zoo_2_0_north" }, + { "point": [0, 1, 0], "overmap": "zoo_0_1_north" }, + { "point": [1, 1, 0], "overmap": "zoo_1_1_north" }, + { "point": [2, 1, 0], "overmap": "zoo_2_1_north" }, + { "point": [0, 2, 0], "overmap": "zoo_0_2_north" }, + { "point": [1, 2, 0], "overmap": "zoo_1_2_north" }, + { "point": [2, 2, 0], "overmap": "zoo_2_2_north" } ], - "flags": [ "CLASSIC" ], - "rotate" : true + "flags": ["CLASSIC"], + "rotate": true } ] ``` @@ -382,14 +384,13 @@ by the frequency assigned to the city building within the `region_settings`. Con ### Fields -| Identifier | Description | +| Identifier | Description | | ----------------- | ----------------------------------------------------------------------------------------------- | | `type` | Must be "overmap_connection". | | `id` | Unique id. | | `default_terrain` | Default `overmap_terrain` to use for undirected connections and existance checks. | | `subtypes` | List of entries used to determine valid locations, terrain cost, and resulting overmap terrain. | - ### Example ```json @@ -398,25 +399,27 @@ by the frequency assigned to the city building within the `region_settings`. Con "type": "overmap_connection", "id": "local_road", "subtypes": [ - { "terrain": "road", "locations": [ "field", "road" ] }, - { "terrain": "road", "locations": [ "forest_without_trail" ], "basic_cost": 20 }, - { "terrain": "road", "locations": [ "forest_trail" ], "basic_cost": 25 }, - { "terrain": "road", "locations": [ "swamp" ], "basic_cost": 40 }, - { "terrain": "road_nesw_manhole", "locations": [ ] }, - { "terrain": "bridge", "locations": [ "water" ], "basic_cost": 120 } + { "terrain": "road", "locations": ["field", "road"] }, + { "terrain": "road", "locations": ["forest_without_trail"], "basic_cost": 20 }, + { "terrain": "road", "locations": ["forest_trail"], "basic_cost": 25 }, + { "terrain": "road", "locations": ["swamp"], "basic_cost": 40 }, + { "terrain": "road_nesw_manhole", "locations": [] }, + { "terrain": "bridge", "locations": ["water"], "basic_cost": 120 } ] }, { "type": "overmap_connection", "id": "subway_tunnel", - "subtypes": [ { "terrain": "subway", "locations": [ "subterranean_subway" ], "flags": [ "ORTHOGONAL" ] } ] + "subtypes": [ + { "terrain": "subway", "locations": ["subterranean_subway"], "flags": ["ORTHOGONAL"] } + ] } ] ``` ### Subtypes -| Identifier | Description | +| Identifier | Description | | ------------ | ---------------------------------------------------------------------------------------------------------- | | `terrain` | `overmap_terrain` to be placed when the placement location matches `locations`. | | `locations` | List of `overmap_location` that this subtype applies to. Can be empty; signifies `terrain` is valid as is. | @@ -427,13 +430,12 @@ by the frequency assigned to the city building within the `region_settings`. Con ### Fields -| Identifier | Description | +| Identifier | Description | | ---------- | ----------------------------------------------------------------------- | | `type` | Must be "overmap_location". | | `id` | Unique id. | | `terrains` | List of `overmap_terrain` that can be considered part of this location. | - ### Example ```json @@ -441,8 +443,7 @@ by the frequency assigned to the city building within the `region_settings`. Con { "type": "overmap_location", "id": "wilderness", - "terrains": [ "forest", "forest_thick", "field", "forest_trail" ] + "terrains": ["forest", "forest_thick", "field", "forest_trail"] } ] - ``` diff --git a/doc/PLAYER_ACTIVITY.md b/doc/PLAYER_ACTIVITY.md index a67f993a4be7..831fc79698ce 100644 --- a/doc/PLAYER_ACTIVITY.md +++ b/doc/PLAYER_ACTIVITY.md @@ -1,71 +1,63 @@ # Activities -Activities are long term actions, that can be interrupted and (optionally) -continued. This allows the avatar or an npc to react to events (like -monsters appearing, getting hurt) while doing something that takes more -than just one turn. +Activities are long term actions, that can be interrupted and (optionally) continued. This allows +the avatar or an npc to react to events (like monsters appearing, getting hurt) while doing +something that takes more than just one turn. ## Adding new activities -1. `player_activities.json` Define properties that apply to all instances -of the activity in question. +1. `player_activities.json` Define properties that apply to all instances of the activity in + question. -2. `activity_actor.h` Create a new subclass of `activity_actor` -(e.g. move_items_activity_actor) to store state and handle turns of the -new activity. +2. `activity_actor.h` Create a new subclass of `activity_actor` (e.g. move_items_activity_actor) to + store state and handle turns of the new activity. -3. `activity_actor.cpp` Define the `start`, `do_turn`, and `finish` -functions needed for the new actor as well as the required serialization -functions. Don't forget to add the deserialization function of your new -activity actor to the `deserialize_functions` map towards the bottom of -`activity_actor.cpp`. Define `canceled` function if activity modifies -some complex state that should be restored upon cancellation / interruption. +3. `activity_actor.cpp` Define the `start`, `do_turn`, and `finish` functions needed for the new + actor as well as the required serialization functions. Don't forget to add the deserialization + function of your new activity actor to the `deserialize_functions` map towards the bottom of + `activity_actor.cpp`. Define `canceled` function if activity modifies some complex state that + should be restored upon cancellation / interruption. -4. If this activity is resumable, `override` -`activity_actor::can_resume_with_internal` +4. If this activity is resumable, `override` `activity_actor::can_resume_with_internal` -5. Construct your activity actor and then pass it to the constructor for -`player_activity`. The newly constructed activity can then be assigned -to the character and started using `Character::assign_activity`. +5. Construct your activity actor and then pass it to the constructor for `player_activity`. The + newly constructed activity can then be assigned to the character and started using + `Character::assign_activity`. ## JSON Properties -* verb: A descriptive term to describe the activity to be used in the -query to stop the activity, and strings that describe it, for example: -`"verb": "mining"` or -`"verb": { "ctxt": "instrument", "str": "playing" }`. +- verb: A descriptive term to describe the activity to be used in the query to stop the activity, + and strings that describe it, for example: `"verb": "mining"` or + `"verb": { "ctxt": "instrument", "str": "playing" }`. -* suspendable (true): If true, the activity can be continued without -starting from scratch again. This is only possible if `can_resume_with()` -returns true. +- suspendable (true): If true, the activity can be continued without starting from scratch again. + This is only possible if `can_resume_with()` returns true. -* rooted (false): If true, then during the activity, recoil is reduced, -and plant mutants sink their roots into the ground. Should be true if the -activity lasts longer than a few minutes, and can always be accomplished -without moving your feet. +- rooted (false): If true, then during the activity, recoil is reduced, and plant mutants sink their + roots into the ground. Should be true if the activity lasts longer than a few minutes, and can + always be accomplished without moving your feet. -* based_on: Can be 'time', 'speed', or 'neither'. +- based_on: Can be 'time', 'speed', or 'neither'. - * time: The amount that `player_activity::moves_left` is - decremented by is independent from the character's speed. + - time: The amount that `player_activity::moves_left` is decremented by is independent from the + character's speed. - * speed: `player_activity::moves_left` may be decremented faster - or slower, depending on the character's speed. + - speed: `player_activity::moves_left` may be decremented faster or slower, depending on the + character's speed. - * neither: `moves_left` will not be decremented. Thus you must - define a do_turn function; otherwise the activity will never end! + - neither: `moves_left` will not be decremented. Thus you must define a do_turn function; + otherwise the activity will never end! -* no_resume (false): Rather than resuming, you must always restart the -activity from scratch. +- no_resume (false): Rather than resuming, you must always restart the activity from scratch. -* multi_activity(false): This activity will repeat until it cannot do -any more work, used for NPC and avatar zone activities. +- multi_activity(false): This activity will repeat until it cannot do any more work, used for NPC + and avatar zone activities. -* refuel_fires( false ): If true, the character will automatically refuel -fires during the long activity. +- refuel_fires( false ): If true, the character will automatically refuel fires during the long + activity. -* auto_needs( false ) : If true, the character will automatically eat and -drink from specific auto_consume zones during long activities. +- auto_needs( false ) : If true, the character will automatically eat and drink from specific + auto_consume zones during long activities. ## Termination @@ -73,71 +65,61 @@ There are several ways an activity can be ended: 1. Call `player_activity::set_to_null()` - This can be called if it finished early or something went wrong, - such as corrupt data, disappearing items, etc. The activity will - not be put into the backlog. + This can be called if it finished early or something went wrong, such as corrupt data, + disappearing items, etc. The activity will not be put into the backlog. 2. `moves_left` <= 0 - Once this condition is true, the finish function, if there is one, - is called. The finish function should call `set_to_null()`. If - there isn't a finish function, `set_to_null()` will be called - for you (from activity_actor::do_turn). + Once this condition is true, the finish function, if there is one, is called. The finish function + should call `set_to_null()`. If there isn't a finish function, `set_to_null()` will be called for + you (from activity_actor::do_turn). 3. `Character::cancel_activity` - Canceling an activity prevents the `activity_actor::finish` - function from running, and the activity does therefore not yield a - result. Instead, `activity_actor::canceled` is called. If activity is - suspendable, a copy of it is written to `Character::backlog`. + Canceling an activity prevents the `activity_actor::finish` function from running, and the + activity does therefore not yield a result. Instead, `activity_actor::canceled` is called. If + activity is suspendable, a copy of it is written to `Character::backlog`. ## Notes -While the character performs the activity, -`activity_actor::do_turn` is called on each turn. Depending on the -JSON properties, this will do some stuff. It will also call the do_turn -function, and if `moves_left` is non-positive, the finish function. +While the character performs the activity, `activity_actor::do_turn` is called on each turn. +Depending on the JSON properties, this will do some stuff. It will also call the do_turn function, +and if `moves_left` is non-positive, the finish function. -Some activities (like playing music on a mp3 player) don't have an end -result but instead do something each turn (playing music on the mp3 -player decreases its batteries and gives a morale bonus). +Some activities (like playing music on a mp3 player) don't have an end result but instead do +something each turn (playing music on the mp3 player decreases its batteries and gives a morale +bonus). -If the activity needs any information during its execution or when -it's finished (like *where* to do something, *which* item to use to do -something, ...), simply add data members to your activity actor as well -as serialization functions for the data so that the activity can persist -across save/load cycles. +If the activity needs any information during its execution or when it's finished (like _where_ to do +something, _which_ item to use to do something, ...), simply add data members to your activity actor +as well as serialization functions for the data so that the activity can persist across save/load +cycles. -Be careful when storing coordinates as the activity may be carried out -by NPCS. If its, the coordinates must be absolute not local as local -coordinates are based on the avatars position. +Be careful when storing coordinates as the activity may be carried out by NPCS. If its, the +coordinates must be absolute not local as local coordinates are based on the avatars position. ### `activity_actor::start` -This function is called exactly once when the activity -is assigned to a character. It is useful for setting -`player_activity::moves_left`/`player_activity::moves_total` in the case -of an activity based on time or speed. +This function is called exactly once when the activity is assigned to a character. It is useful for +setting `player_activity::moves_left`/`player_activity::moves_total` in the case of an activity +based on time or speed. ### `activity_actor::do_turn` -To prevent an infinite loop, ensure that one of the following is -satisfied: +To prevent an infinite loop, ensure that one of the following is satisfied: - The `based_on` JSON property is `speed` or `time` - The `player_activity::moves_left` is decreased in `do_turn` -- The the activity is stopped in `do_turn` (see 'Termination' above) +- The the activity is stopped in `do_turn` (see 'Termination' above) -For example, `move_items_activity_actor::do_turn` will either move as -many items as possible given the character's current moves or, if there -are no target items remaining, terminate the activity. +For example, `move_items_activity_actor::do_turn` will either move as many items as possible given +the character's current moves or, if there are no target items remaining, terminate the activity. ### `activity_actor::finish` -This function is called when the activity has been completed -(`moves_left` <= 0). It must call `player_activity::set_to_null()` or -assign a new activity. One should not call `Character::cancel_activity` -for the finished activity, as this could make a copy of the activity in +This function is called when the activity has been completed (`moves_left` <= 0). It must call +`player_activity::set_to_null()` or assign a new activity. One should not call +`Character::cancel_activity` for the finished activity, as this could make a copy of the activity in `Character::backlog`, which allows resuming an already finished activity. diff --git a/doc/POINTS_COORDINATES.md b/doc/POINTS_COORDINATES.md index 35ca4d9bf2d9..eb3fa00444a0 100644 --- a/doc/POINTS_COORDINATES.md +++ b/doc/POINTS_COORDINATES.md @@ -3,127 +3,113 @@ ## Axes The game is three-dimensional, with the axes oriented as follows: -* The **x-axis** goes from left to right across the display (in non-isometric - views). -* The **y-axis** goes from top to bottom of the display. -* The **z-axis** is vertical, with negative z pointing underground and positive - z pointing to the sky. + +- The **x-axis** goes from left to right across the display (in non-isometric views). +- The **y-axis** goes from top to bottom of the display. +- The **z-axis** is vertical, with negative z pointing underground and positive z pointing to the + sky. ## Coordinate systems -CDDA uses a variety of coordinate systems for different purposes. These differ -by scale and origin. +CDDA uses a variety of coordinate systems for different purposes. These differ by scale and origin. -The most precise coordinates are **map square** (ms) coordinates. These refer to -the tiles you see normally when playing the game. +The most precise coordinates are **map square** (ms) coordinates. These refer to the tiles you see +normally when playing the game. Two origins for map square coordinates are common: -* **Absolute** coordinates, sometimes called global, which are a global system - for the whole game, relative to a fixed origin. -* **Local** coordinates, which are relative to the corner of the current "reality - bubble", or `map` roughly centered on the avatar. In local map square - coordinates, `x` and `y` values will both fall in the range [0,`MAPSIZE_X`). -The next scale is **submap** (sm) coordinates. One submap is 12x12 -(`SEEX`x`SEEY`) map squares. Submaps are the scale at which chunks of the map -are loaded or saved as they enter or leave the reality bubble. +- **Absolute** coordinates, sometimes called global, which are a global system for the whole game, + relative to a fixed origin. +- **Local** coordinates, which are relative to the corner of the current "reality bubble", or `map` + roughly centered on the avatar. In local map square coordinates, `x` and `y` values will both fall + in the range [0,`MAPSIZE_X`). + +The next scale is **submap** (sm) coordinates. One submap is 12x12 (`SEEX`x`SEEY`) map squares. +Submaps are the scale at which chunks of the map are loaded or saved as they enter or leave the +reality bubble. -Next comes **overmap terrain** (omt) coordinates. One overmap terrain is 2x2 -submaps. Overmap terrains correspond to a single tile on the map view in-game, -and are the scale of chunk of mapgen. +Next comes **overmap terrain** (omt) coordinates. One overmap terrain is 2x2 submaps. Overmap +terrains correspond to a single tile on the map view in-game, and are the scale of chunk of mapgen. -Largest are **overmap** (om) coordinates. One overmap is 180x180 -(`OMAPX`x`OMAPY`) overmap terrains. Large-scale mapgen (e.g. city layout) -happens one overmap at a time. +Largest are **overmap** (om) coordinates. One overmap is 180x180 (`OMAPX`x`OMAPY`) overmap terrains. +Large-scale mapgen (e.g. city layout) happens one overmap at a time. -Lastly, these is a system called **segment** (seg) coordinates. These are only -used in saving/loading submaps and you are unlikely to encounter them. +Lastly, these is a system called **segment** (seg) coordinates. These are only used in +saving/loading submaps and you are unlikely to encounter them. -As well as absolute and local coordinates, sometimes we need to use coordinates -relative so some larger scale. For example, when performing mapgen for a -single overmap, we want to work with coordinates within that overmap. This -will be an overmap terrain-scale point relative to the corner of its containing -overmap, and so typically take `x` and `y` values in the range [0,180). +As well as absolute and local coordinates, sometimes we need to use coordinates relative so some +larger scale. For example, when performing mapgen for a single overmap, we want to work with +coordinates within that overmap. This will be an overmap terrain-scale point relative to the corner +of its containing overmap, and so typically take `x` and `y` values in the range [0,180). ## Vertical coordinates -Although `x` and `y` coordinates work at all these various scales, `z` -coordinates are consistent across all contexts. They lie in the range -[-`OVERMAP_DEPTH`,`OVERMAP_HEIGHT`]. +Although `x` and `y` coordinates work at all these various scales, `z` coordinates are consistent +across all contexts. They lie in the range [-`OVERMAP_DEPTH`,`OVERMAP_HEIGHT`]. ## Vehicle coordinates -Each vehicle has its own origin point, which will be at a particular part of -the vehicle (e.g. it might be at the driver's seat). The origin can move if -the vehicle is damaged and all the vehicle parts at that location are -destroyed. +Each vehicle has its own origin point, which will be at a particular part of the vehicle (e.g. it +might be at the driver's seat). The origin can move if the vehicle is damaged and all the vehicle +parts at that location are destroyed. Vehicles use two systems of coordinates relative to their origin: -* **mount** coordinates provide a location for vehicle parts that does not - change as the vehicle moves. It is the map square of that part, relative to - the vehicle origin, when the vehicle is facing due east. +- **mount** coordinates provide a location for vehicle parts that does not change as the vehicle + moves. It is the map square of that part, relative to the vehicle origin, when the vehicle is + facing due east. -* **map square** is the map square, relative to the origin, but accounting for - the vehicle's current facing. +- **map square** is the map square, relative to the origin, but accounting for the vehicle's current + facing. -Vehicle facing is implemented via a combination of rotations (by quarter turns) -and shearing to interpolate between quarter turns. The logic to convert -between vehicle mount and map square coordinates is complicated and handled by -the `vehicle::coord_translate()` and `vehicle::mount_to_tripoint()` families of -functions. +Vehicle facing is implemented via a combination of rotations (by quarter turns) and shearing to +interpolate between quarter turns. The logic to convert between vehicle mount and map square +coordinates is complicated and handled by the `vehicle::coord_translate()` and +`vehicle::mount_to_tripoint()` families of functions. -Currently, vehicle mount coordinates do not have a z-level component, but -vehicle map square coordinates do. The z coordinate is relative to the vehicle -origin. +Currently, vehicle mount coordinates do not have a z-level component, but vehicle map square +coordinates do. The z coordinate is relative to the vehicle origin. ## Point types -To work with these coordinate systems we have a variety of types. These are -defined in [`coordinates.h`](../src/coordinates.h). For example, we have -`point_abs_ms` for absolute map-square coordinates. The three parts of the -type name are *dimension*`_`*origin*`_`*scale*. - -* **dimension** is either `point` for two-dimensional or `tripoint` for - three-dimensional. -* **origin** specifies what the value is relative to, and can be: - * `rel` means relative to some arbitrary point. This is the result of - subtracting two points with a common origin. It would be used for example - to represent the offset between the avatar and a monster they are shooting - at. - * `abs` means global absolute coordinates. - * `sm` means relative to a corner of a submap. - * `omt` means relative to a corner of an overmap terrain. - * `om` means relative to a corner of an overmap. - * `veh` means relative to a vehicle origin. -* **scale** means the scale as discussed above. - * `ms` for map square. - * `sm` for submap. - * `omt` for overmap terrain. - * `seg` for segment. - * `om` for overmap. - * `mnt` for vehicle mount coordinates (only relevant for the `veh` origin). +To work with these coordinate systems we have a variety of types. These are defined in +[`coordinates.h`](../src/coordinates.h). For example, we have `point_abs_ms` for absolute map-square +coordinates. The three parts of the type name are _dimension_ `_` _origin_ `_` _scale_. + +- **dimension** is either `point` for two-dimensional or `tripoint` for three-dimensional. +- **origin** specifies what the value is relative to, and can be: + - `rel` means relative to some arbitrary point. This is the result of subtracting two points with + a common origin. It would be used for example to represent the offset between the avatar and a + monster they are shooting at. + - `abs` means global absolute coordinates. + - `sm` means relative to a corner of a submap. + - `omt` means relative to a corner of an overmap terrain. + - `om` means relative to a corner of an overmap. + - `veh` means relative to a vehicle origin. +- **scale** means the scale as discussed above. + - `ms` for map square. + - `sm` for submap. + - `omt` for overmap terrain. + - `seg` for segment. + - `om` for overmap. + - `mnt` for vehicle mount coordinates (only relevant for the `veh` origin). ## Raw point types -As well as these types with origin and scale encoded into the type, there are -simple raw point types called just `point` and `tripoint`. These can be used -when no particular game scale is intended. +As well as these types with origin and scale encoded into the type, there are simple raw point types +called just `point` and `tripoint`. These can be used when no particular game scale is intended. -At time of writing we are still in the process of transitioning the codebase -away from using these raw point types everywhere, so you are likely to see -legacy code using them in places where the more type-safe points might seem -appropriate. +At time of writing we are still in the process of transitioning the codebase away from using these +raw point types everywhere, so you are likely to see legacy code using them in places where the more +type-safe points might seem appropriate. -New code should prefer to use the types which include their coordinate system -where feasible. +New code should prefer to use the types which include their coordinate system where feasible. ## Converting between point types ### Changing scale -To change the scale of a point without changing its origin, use `project_to`. -For example: +To change the scale of a point without changing its origin, use `project_to`. For example: ```c++ point_abs_ms pos_ms = get_avatar()->global_square_location().xy(); @@ -131,17 +117,15 @@ point_abs_omt pos_omt = project_to( pos_ms ); assert( pos_omt == get_avatar()->global_omt_location().xy() ); ``` -The same function `project_to` can be used for scaling up or down. When -converting to a coarser coordinate system precision is of course lost. If you -care about the remainder then you must instead use `project_remain`. +The same function `project_to` can be used for scaling up or down. When converting to a coarser +coordinate system precision is of course lost. If you care about the remainder then you must instead +use `project_remain`. -`project_remain` allows you to convert to a coarser coordinate system and also -capture the remainder relative to that coarser point. It returns a helper -struct intended to be used with -[`std::tie`](https://en.cppreference.com/w/cpp/utility/tuple/tie) to capture -the two parts of the result. For example, suppose you want to know which -overmap the avatar is in, and which overmap terrain they are in within that -overmap. +`project_remain` allows you to convert to a coarser coordinate system and also capture the remainder +relative to that coarser point. It returns a helper struct intended to be used with +[`std::tie`](https://en.cppreference.com/w/cpp/utility/tuple/tie) to capture the two parts of the +result. For example, suppose you want to know which overmap the avatar is in, and which overmap +terrain they are in within that overmap. ```c++ point_abs_omt abs_pos = get_avatar()->global_omt_location().xy(); @@ -150,14 +134,12 @@ point_om_omt omt_within_overmap; std::tie( overmap, omt_within_overmap ) = project_remain( abs_pos ); ``` -That makes sense for two-dimensional `point` types, but how does it handle -`tripoint`? Recall that the z-coordinates do not scale along with the -horizontal dimensions, so `z` values are unchanged by `project_to` and -`project_remain`. However, for `project_remain` we don't want to duplicate the -z-coordinate in both parts of the result, so you must choose exactly one to be -a `tripoint`. In the example above, z-coodinates do not have much meaning at -the overmap scale, so you probably want the z-coordinate in -`omt_within_overmap`. That can be done as follows: +That makes sense for two-dimensional `point` types, but how does it handle `tripoint`? Recall that +the z-coordinates do not scale along with the horizontal dimensions, so `z` values are unchanged by +`project_to` and `project_remain`. However, for `project_remain` we don't want to duplicate the +z-coordinate in both parts of the result, so you must choose exactly one to be a `tripoint`. In the +example above, z-coodinates do not have much meaning at the overmap scale, so you probably want the +z-coordinate in `omt_within_overmap`. That can be done as follows: ```c++ tripoint_abs_omt abs_pos = get_avatar()->global_omt_location(); @@ -166,11 +148,10 @@ tripoint_om_omt omt_within_overmap; std::tie( overmap, omt_within_overmap ) = project_remain( abs_pos ); ``` -The last available operation for rescaling points is `project_combine`. This -performs the opposite operation from `project_remain`. Given two points where -the origin of the second matches the scale of the first, you can combine them -into a single value. As you might expect from the above discussion, one of -these two can be a `tripoint`, but not both. +The last available operation for rescaling points is `project_combine`. This performs the opposite +operation from `project_remain`. Given two points where the origin of the second matches the scale +of the first, you can combine them into a single value. As you might expect from the above +discussion, one of these two can be a `tripoint`, but not both. ```c++ tripoint_abs_omt abs_pos = get_avatar()->global_omt_location(); @@ -183,25 +164,23 @@ assert( abs_pos == abs_pos_again ); ### Changing origin -`project_remain` and `project_combine` facilitate some changes of origin, but -only those origins specifically related to rescaling. To convert to or from -local or vehicle coordinates requires a specific `map` or `vehicle` object. +`project_remain` and `project_combine` facilitate some changes of origin, but only those origins +specifically related to rescaling. To convert to or from local or vehicle coordinates requires a +specific `map` or `vehicle` object. TODO: write some examples once this is implemented. ## Point operations -We provide standard arithmetic operations as overloaded operators, but limit -them to prevent bugs. For example, most point types cannot be multiplied by a -constant, but ones with the `rel` origin can (it makes sense to say "half as -far in the same direction"). +We provide standard arithmetic operations as overloaded operators, but limit them to prevent bugs. +For example, most point types cannot be multiplied by a constant, but ones with the `rel` origin can +(it makes sense to say "half as far in the same direction"). -Similarly, you can't generally add two points together, but you can when one of -them has the `rel` origin, or if one of them is a raw point type. +Similarly, you can't generally add two points together, but you can when one of them has the `rel` +origin, or if one of them is a raw point type. -For computing distances a variety of functions are available, depending on your -requirements: `square_dist`, `trig_dist`, `rl_dist`, `manhattan_dist`. Other -related utility functions include `direction_from` and `line_to`. +For computing distances a variety of functions are available, depending on your requirements: +`square_dist`, `trig_dist`, `rl_dist`, `manhattan_dist`. Other related utility functions include +`direction_from` and `line_to`. -To iterate over nearby points of the same type you can use -`closest_points_first`. +To iterate over nearby points of the same type you can use `closest_points_first`. diff --git a/doc/POSTAPOC_PRICE_GUIDE.md b/doc/POSTAPOC_PRICE_GUIDE.md index 21936530b661..a9856a2f764c 100644 --- a/doc/POSTAPOC_PRICE_GUIDE.md +++ b/doc/POSTAPOC_PRICE_GUIDE.md @@ -1,23 +1,26 @@ # How to give items a sensible postapoc_price value ### Pricing philosophy -Prices were based on the philosophy that there is a decent portion of humanity unwilling to regularly -brave the risks of city scavenging, that are always on the lookout for supplies to stay alive. -This mean food and medicine are relatively quite valuable compared to the goods you would use to acquire them. -**The standard unit of currency**, the free merchants note, is priced to be the equivalent to -**one piece of meat jerky (250 cents)**. +Prices were based on the philosophy that there is a decent portion of humanity unwilling to +regularly brave the risks of city scavenging, that are always on the lookout for supplies to stay +alive. This mean food and medicine are relatively quite valuable compared to the goods you would use +to acquire them. + +**The standard unit of currency**, the free merchants note, is priced to be the equivalent to **one +piece of meat jerky (250 cents)**. One piece of meat jerky will stay fresh for 24 days, a decent time, and contains 347 calories. -A survivor that bring back 2000 cents worth of goods back to the merchants every day is -doing well enough to eke out a subsistence living. +A survivor that bring back 2000 cents worth of goods back to the merchants every day is doing well +enough to eke out a subsistence living. A survivor that brings back 4000 cents worth of goods every day is doing quite well for himself. #### Items are priced on a combination of their availability and their utility. -Raw materials tend to either be worthless, or only somewhat worthwhile if you can get them in bulk ~(0-25)/kg. +Raw materials tend to either be worthless, or only somewhat worthwhile if you can get them in bulk +~(0-25)/kg. Common items with no utility are worthless. @@ -31,10 +34,12 @@ Rare items with some theoretical utility are worth ~(100-500). Rare items with considerable use tend to have the highest variety in prices ~(1000-15000). -**No item should be worth more than 150000.** They might be worth more if the economy was larger but that's -pretty much the most anyone will be willing to spend on any one thing, no matter how nice it is. +**No item should be worth more than 150000.** They might be worth more if the economy was larger but +that's pretty much the most anyone will be willing to spend on any one thing, no matter how nice it +is. #### Currently Implemented faction currencies + "id": "FMCNote", "description": "The Free Merchant Certified Note, also known by names such as a 'c-note' or 'merch', is a currency based on old American bills. Fifty dollar bills and larger are printed with a promissory note signed by the treasurer of the Free Merchants, along with a complex design. The note explains that this can be exchanged for food, water, and other services through the Free Merchants in the Refugee Center.", "name": { "str": "Merch" }, @@ -45,8 +50,8 @@ pretty much the most anyone will be willing to spend on any one thing, no matter "name": { "str": "Hub 01 Gold Coin" }, "description": "This is a small but surprisingly heavy gold coin. One side is etched with circuitry and the other side reads 'Hub 01 exchange currency'.", "price_postapoc": 5000 - - + + "id": "FlatCoin", "name": { "str": "FlatCoin" }, "description": "This is a coin that has been flattened in a novelty coin flattening machine. The machine has been somewhat crudely altered so that the design - which appears to once have been Mickey Mouse - is overlaid with a handwritten emblem of a book. There is some text that faintly reads 'Campus Exchange Token'.", @@ -63,43 +68,44 @@ pretty much the most anyone will be willing to spend on any one thing, no matter "name": { "str": "icon" }, "description": "This is a small picture, about the same size as an ID card, symbolizing a religious figure. On the back, there is a text that faintly reads 'New England Church Community'.", "price_postapoc": 250 - - + ##### Some benchmark prices ``` - { - "id": "antibiotics", - "name": { "str_sp": "antibiotics" }, - "description": "A strong antibacterial medication designed to prevent or stop the spread of infection. It's the safest way to cure any infections you might have. One dose lasts twelve hours.", - "price_postapoc": 40000, - "charges": 15, - "stack_size": 200, - "flags": [ "NPC_SAFE", "IRREPLACEABLE_CONSUMABLE" ] - }, - { - "id": "boltcutters", - "type": "TOOL", - "name": { "str": "pair of bolt cutters", "str_pl": "pairs of bolt cutters" }, - "description": "This is a large pair of bolt cutters. You could use them to cut padlocks or heavy gauge wire.", - "price_postapoc": 250, - }, - { - "id": "armor_lightplate", - "name": { "str": "plate armor" }, - "description": "A suit of Gothic plate armor.", - "price_postapoc": 12000, - }, - { - "id": "bat_metal", - "name": { "str": "aluminum bat" }, - "description": "An aluminum baseball bat, lighter than a wooden bat and a little easier to swing as a result.", - "price_postapoc": 1250, - }, +{ + "id": "antibiotics", + "name": { "str_sp": "antibiotics" }, + "description": "A strong antibacterial medication designed to prevent or stop the spread of infection. It's the safest way to cure any infections you might have. One dose lasts twelve hours.", + "price_postapoc": 40000, + "charges": 15, + "stack_size": 200, + "flags": [ "NPC_SAFE", "IRREPLACEABLE_CONSUMABLE" ] +}, +{ + "id": "boltcutters", + "type": "TOOL", + "name": { "str": "pair of bolt cutters", "str_pl": "pairs of bolt cutters" }, + "description": "This is a large pair of bolt cutters. You could use them to cut padlocks or heavy gauge wire.", + "price_postapoc": 250, +}, +{ + "id": "armor_lightplate", + "name": { "str": "plate armor" }, + "description": "A suit of Gothic plate armor.", + "price_postapoc": 12000, +}, +{ + "id": "bat_metal", + "name": { "str": "aluminum bat" }, + "description": "An aluminum baseball bat, lighter than a wooden bat and a little easier to swing as a result.", + "price_postapoc": 1250, +}, ``` #### Food pricing -Food is priced mostly for a combination of calories, how preservable they are, and how nutritious they are. + +Food is priced mostly for a combination of calories, how preservable they are, and how nutritious +they are. Meat jerky is 250. @@ -108,14 +114,19 @@ Food that has more calories, is canned, and is very nutritious might be 500. Food that has less calories, goes bad quickly, and is junk food, might be 50. #### Stack size -For items that have a stack size, you need to **divide** the price by stack size find the price per unit of the item. + +For items that have a stack size, you need to **divide** the price by stack size find the price per +unit of the item. #### IRREPLACEABLE_CONSUMABLE Flag + Pre cataclysm consumables that can not be replaced can be given the flag: + ``` - "flags": [ "IRREPLACEABLE_CONSUMABLE" ], +"flags": [ "IRREPLACEABLE_CONSUMABLE" ], ``` -This is used for things such as unreloaded ammo, medicine, and luxury consumables such as coffee and tea. +This is used for things such as unreloaded ammo, medicine, and luxury consumables such as coffee and +tea. In the future we can implement a feature that will allow this items to increase in price over time. diff --git a/doc/REGION_SETTINGS.md b/doc/REGION_SETTINGS.md index 90fb07918cd7..9e95659ade61 100644 --- a/doc/REGION_SETTINGS.md +++ b/doc/REGION_SETTINGS.md @@ -1,10 +1,10 @@ # Region Settings -The **region_settings** define the attributes for map generation that apply to an entire region. -The general settings define the default overmap terrain and ground cover. Additional sections are -as follows: +The **region_settings** define the attributes for map generation that apply to an entire region. The +general settings define the default overmap terrain and ground cover. Additional sections are as +follows: -| Section | Description | +| Section | Description | | ------------------------------- | --------------------------------------------------------------------- | | `region_terrain_and_furniture` | Defines the resolution of regional terrain/furniture to actual types. | | `field_coverage` | Defines the flora that cover the `field` overmap terrain. | @@ -21,78 +21,78 @@ Note that for the default region, all attributes and sections are required. ### Fields -| Identifier | Description | -| ----------------------- | ------------------------------------------------------------------ | -| `type` | Type identifier. Must be "region_settings". | -| `id` | Unique identfier for this region. | -| `default_oter` | Default overmap terrain for this region. | -| `default_groundcover` | List of terrain types and weights applied as default ground cover. | - +| Identifier | Description | +| --------------------- | ------------------------------------------------------------------ | +| `type` | Type identifier. Must be "region_settings". | +| `id` | Unique identfier for this region. | +| `default_oter` | Default overmap terrain for this region. | +| `default_groundcover` | List of terrain types and weights applied as default ground cover. | ### Example + ```json { - "type": "region_settings", - "id": "default", - "default_oter": "field", - "default_groundcover": [ - ["t_grass", 4], - ["t_dirt", 1] - ] + "type": "region_settings", + "id": "default", + "default_oter": "field", + "default_groundcover": [ + ["t_grass", 4], + ["t_dirt", 1] + ] } ``` ## Region Terrain / Furniture -The **region_terrain_and_furniture** section defines the resolution of regional terrain/furniture -to their actual terrain and furniture types for the region, with a weighted list for -terrain/furniture entry that defines the relative weight of a given entry when mapgen resolves the -regional entry to an actual entry. +The **region_terrain_and_furniture** section defines the resolution of regional terrain/furniture to +their actual terrain and furniture types for the region, with a weighted list for terrain/furniture +entry that defines the relative weight of a given entry when mapgen resolves the regional entry to +an actual entry. ### Fields -| Identifier | Description | +| Identifier | Description | | ----------- | ------------------------------------------------------------------ | | `terrain` | List of regional terrain and their corresponding weighted lists. | | `furniture` | List of regional furniture and their corresponding weighted lists. | ### Example + ```json { - "region_terrain_and_furniture": { - "terrain": { - "t_region_groundcover": { - "t_grass": 4, - "t_grass_long": 2, - "t_dirt": 1 - } - }, - "furniture": { - "f_region_flower": { - "f_black_eyed_susan": 1, - "f_lily": 1, - "f_flower_tulip": 1, - "f_flower_spurge": 1, - "f_chamomile": 1, - "f_dandelion": 1, - "f_datura": 1, - "f_dahlia": 1, - "f_bluebell": 1 - } - } - } + "region_terrain_and_furniture": { + "terrain": { + "t_region_groundcover": { + "t_grass": 4, + "t_grass_long": 2, + "t_dirt": 1 + } + }, + "furniture": { + "f_region_flower": { + "f_black_eyed_susan": 1, + "f_lily": 1, + "f_flower_tulip": 1, + "f_flower_spurge": 1, + "f_chamomile": 1, + "f_dandelion": 1, + "f_datura": 1, + "f_dahlia": 1, + "f_bluebell": 1 + } + } + } } ``` - ## Field Coverage -The **field_coverage** section defines the furniture and terrain that make up the flora that -cover the `field` overmap terrain. +The **field_coverage** section defines the furniture and terrain that make up the flora that cover +the `field` overmap terrain. ### Fields -| Identifier | Description | +| Identifier | Description | | -------------------------- | ---------------------------------------------------------------------------- | | `percent_coverage` | % of tiles in the overmap terrain that have a plant. | | `default_ter` | Default terrain feature for plants. | @@ -103,24 +103,25 @@ cover the `field` overmap terrain. | `boosted_other_percent` | % of `boosted_percent_coverage` that will be covered by `boosted_other`. | ### Example + ```json { - "field_coverage": { - "percent_coverage": 0.9333, - "default_ter": "t_shrub", - "other": { - "t_shrub_blueberry": 0.4166, - "t_shrub_strawberry": 0.4166, - "f_mutpoppy": 8.3333 - }, - "boost_chance": 0.833, - "boosted_percent_coverage": 2.5, - "boosted_other": { - "t_shrub_blueberry": 40.0, - "f_dandelion": 6.6 - }, - "boosted_other_percent": 50.0 - } + "field_coverage": { + "percent_coverage": 0.9333, + "default_ter": "t_shrub", + "other": { + "t_shrub_blueberry": 0.4166, + "t_shrub_strawberry": 0.4166, + "f_mutpoppy": 8.3333 + }, + "boost_chance": 0.833, + "boosted_percent_coverage": 2.5, + "boosted_other": { + "t_shrub_blueberry": 40.0, + "f_dandelion": 6.6 + }, + "boosted_other_percent": 50.0 + } } ``` @@ -128,12 +129,12 @@ cover the `field` overmap terrain. The **overmap_lake_settings** section defines the attributes used in generating lakes on the overmap. The actual placement of these features is determined globally across all overmaps so that -the edges of the features align, and these parameters are mostly about how those global features -are interpreted. +the edges of the features align, and these parameters are mostly about how those global features are +interpreted. ### Fields -| Identifier | Description | +| Identifier | Description | | ------------------------------------------ | --------------------------------------------------------------------------- | | `noise_threshold_lake` | [0, 1], x > value spawns a `lake_surface` or `lake_shore`. | | `lake_size_min` | Minimum size of the lake in overmap terrains for it to actually spawn. | @@ -145,28 +146,28 @@ are interpreted. ```json { - "overmap_lake_settings": { - "noise_threshold_lake": 0.25, - "lake_size_min": 20, - "lake_depth": -5, - "shore_extendable_overmap_terrain": ["forest_thick", "forest_water", "field"], - "shore_extendable_overmap_terrain_aliases": [ - { "om_terrain": "forest", "om_terrain_match_type": "TYPE", "alias": "forest_thick" } - ] - } + "overmap_lake_settings": { + "noise_threshold_lake": 0.25, + "lake_size_min": 20, + "lake_depth": -5, + "shore_extendable_overmap_terrain": ["forest_thick", "forest_water", "field"], + "shore_extendable_overmap_terrain_aliases": [ + { "om_terrain": "forest", "om_terrain_match_type": "TYPE", "alias": "forest_thick" } + ] + } } ``` ## Overmap Forest Settings The **overmap_forest_settings** section defines the attributes used in generating forest and swamps -on the overmap. The actual placement of these features is determined globally across all overmaps -so that the edges of the features align, and these parameters are mostly about how those global +on the overmap. The actual placement of these features is determined globally across all overmaps so +that the edges of the features align, and these parameters are mostly about how those global features are interpreted. ### Fields -| Identifier | Description | +| Identifier | Description | | -------------------------------------- | ---------------------------------------------------------------------- | | `noise_threshold_forest` | [0, 1], x > value spawns `forest`. | | `noise_threshold_forest_thick` | [0, 1], x > value spawns `forest_thick`. | @@ -179,37 +180,36 @@ features are interpreted. ```json { - "overmap_forest_settings": { - "noise_threshold_forest": 0.25, - "noise_threshold_forest_thick": 0.3, - "noise_threshold_swamp_adjacent_water": 0.3, - "noise_threshold_swamp_isolated": 0.6, - "river_floodplain_buffer_distance_min": 3, - "river_floodplain_buffer_distance_max": 15 - } + "overmap_forest_settings": { + "noise_threshold_forest": 0.25, + "noise_threshold_forest_thick": 0.3, + "noise_threshold_swamp_adjacent_water": 0.3, + "noise_threshold_swamp_isolated": 0.6, + "river_floodplain_buffer_distance_min": 3, + "river_floodplain_buffer_distance_max": 15 + } } ``` ## Forest Map Generation Settings The **forest_mapgen_settings** section defines the attributes used in generating forest (`forest`, -`forest_thick`, `forest_water`) terrains, including their items, groundcover, terrain and -furniture. +`forest_thick`, `forest_water`) terrains, including their items, groundcover, terrain and furniture. ### General Structure At the top level, the `forest_mapgen_settings` is a collection of named configurations where each entry has the name of the overmap terrain that it applies to, e.g. `forest`, `forest_thick`, -`forest_water`. It is possible to define settings for overmap terrains that are not rendered by -the forest mapgen, but will be used when blending forest terrains with other terrain types. +`forest_water`. It is possible to define settings for overmap terrains that are not rendered by the +forest mapgen, but will be used when blending forest terrains with other terrain types. ```json { - "forest_mapgen_settings": { - "forest": {}, - "forest_thick": {}, - "forest_water": {} - } + "forest_mapgen_settings": { + "forest": {}, + "forest_thick": {}, + "forest_water": {} + } } ``` @@ -217,7 +217,7 @@ Each terrain then has an independent set of configuration values that control th ### Fields -| Identifier | Description | +| Identifier | Description | | ----------------------------- | ---------------------------------------------------------------------------- | | `sparseness_adjacency_factor` | Value relative to neighbors controls how sparse the overmap terrain will be. | | `item_group` | Item group used to place items randomly within the overmap terrain. | @@ -234,21 +234,21 @@ Each terrain then has an independent set of configuration values that control th ```json { - "forest": { - "sparseness_adjacency_factor": 3, - "item_group": "forest", - "item_group_chance": 60, - "item_spawn_iterations": 1, - "clear_groundcover": false, - "groundcover": { - "t_grass": 3, - "t_dirt": 1 - }, - "clear_components": false, - "components": {}, - "clear_terrain_furniture": false, - "terrain_furniture": {} - } + "forest": { + "sparseness_adjacency_factor": 3, + "item_group": "forest", + "item_group_chance": 60, + "item_spawn_iterations": 1, + "clear_groundcover": false, + "groundcover": { + "t_grass": 3, + "t_dirt": 1 + }, + "clear_components": false, + "components": {}, + "clear_terrain_furniture": false, + "terrain_furniture": {} + } } ``` @@ -260,7 +260,7 @@ for the components are only relevant for the purposes of overriding them in regi ### Fields -| Identifier | Description | +| Identifier | Description | | ------------- | -------------------------------------------------------------------- | | `sequence` | Sequence in which components are processed. | | `chance` | One in X chance that something from this component will be placed. | @@ -271,63 +271,62 @@ for the components are only relevant for the purposes of overriding them in regi ```json { - "trees": { - "sequence": 0, - "chance": 12, - "clear_types": false, - "types": { - "t_tree_young": 128, - "t_tree": 32, - "t_tree_birch": 32, - "t_tree_pine": 32, - "t_tree_maple": 32, - "t_tree_willow": 32, - "t_tree_hickory": 32, - "t_tree_blackjack": 8, - "t_tree_coffee": 8, - "t_tree_apple": 2, - "t_tree_apricot": 2, - "t_tree_cherry": 2, - "t_tree_peach": 2, - "t_tree_pear": 2, - "t_tree_plum": 2, - "t_tree_deadpine": 1, - "t_tree_hickory_dead": 1, - "t_tree_dead": 1 - } - }, - "shrubs_and_flowers": { - "sequence": 1, - "chance": 10, - "clear_types": false, - "types": { - "t_underbrush": 8, - "t_shrub_blueberry": 1, - "t_shrub_strawberry": 1, - "t_shrub": 1, - "f_chamomile": 1, - "f_dandelion": 1, - "f_datura": 1, - "f_dahlia": 1, - "f_bluebell": 1, - "f_mutpoppy": 1 - } - } + "trees": { + "sequence": 0, + "chance": 12, + "clear_types": false, + "types": { + "t_tree_young": 128, + "t_tree": 32, + "t_tree_birch": 32, + "t_tree_pine": 32, + "t_tree_maple": 32, + "t_tree_willow": 32, + "t_tree_hickory": 32, + "t_tree_blackjack": 8, + "t_tree_coffee": 8, + "t_tree_apple": 2, + "t_tree_apricot": 2, + "t_tree_cherry": 2, + "t_tree_peach": 2, + "t_tree_pear": 2, + "t_tree_plum": 2, + "t_tree_deadpine": 1, + "t_tree_hickory_dead": 1, + "t_tree_dead": 1 + } + }, + "shrubs_and_flowers": { + "sequence": 1, + "chance": 10, + "clear_types": false, + "types": { + "t_underbrush": 8, + "t_shrub_blueberry": 1, + "t_shrub_strawberry": 1, + "t_shrub": 1, + "f_chamomile": 1, + "f_dandelion": 1, + "f_datura": 1, + "f_dahlia": 1, + "f_bluebell": 1, + "f_mutpoppy": 1 + } + } } ``` ### Terrain Furniture -The terrain furniture are a collection of terrain ids with a chance of having furniture -picked from a weighted list for that given terrain and placed on it during mapgen after -the normal mapgen has completed. This is used, for example, to place cattails on fresh -water in swamps. Cattails could be simply placed in the `components` section and placed -during the normal forest mapgen, but that would not guarantee their placement on fresh -water only, while this does. +The terrain furniture are a collection of terrain ids with a chance of having furniture picked from +a weighted list for that given terrain and placed on it during mapgen after the normal mapgen has +completed. This is used, for example, to place cattails on fresh water in swamps. Cattails could be +simply placed in the `components` section and placed during the normal forest mapgen, but that would +not guarantee their placement on fresh water only, while this does. ### Fields -| Identifier | Description | +| Identifier | Description | | ----------------- | ------------------------------------------------------------------ | | `chance` | One in X chance that furniture from this component will be placed. | | `clear_furniture` | Clear all previously defined `furniture` for this terrain. | @@ -337,13 +336,13 @@ water only, while this does. ```json { - "t_water_sh" : { - "chance": 2, - "clear_furniture": false, - "furniture": { - "f_cattails": 1 - } - } + "t_water_sh": { + "chance": 2, + "clear_furniture": false, + "furniture": { + "f_cattails": 1 + } + } } ``` @@ -355,7 +354,7 @@ trailheads, and some general tuning of the actual trail width/position in mapgen ### Fields -| Identifier | Description | +| Identifier | Description | | -------------------------- | ------------------------------------------------------------------------------------------- | | `chance` | One in X chance a contiguous forest will have a trail system. | | `border_point_chance` | One in X chance that the N/S/E/W-most point of the forest will be part of the trail system. | @@ -376,26 +375,26 @@ trailheads, and some general tuning of the actual trail width/position in mapgen ```json { - "forest_trail_settings": { - "chance": 2, - "border_point_chance": 2, - "minimum_forest_size": 100, - "random_point_min": 4, - "random_point_max": 50, - "random_point_size_scalar": 100, - "trailhead_chance": 1, - "trailhead_road_distance": 6, - "trail_center_variance": 3, - "trail_width_offset_min": 1, - "trail_width_offset_max": 3, - "clear_trail_terrain": false, - "trail_terrain": { - "t_dirt": 1 - }, - "trailheads": { - "trailhead_basic": 50 - } - } + "forest_trail_settings": { + "chance": 2, + "border_point_chance": 2, + "minimum_forest_size": 100, + "random_point_min": 4, + "random_point_max": 50, + "random_point_size_scalar": 100, + "trailhead_chance": 1, + "trailhead_road_distance": 6, + "trail_center_variance": 3, + "trail_width_offset_min": 1, + "trail_width_offset_max": 3, + "clear_trail_terrain": false, + "trail_terrain": { + "t_dirt": 1 + }, + "trailheads": { + "trailhead_basic": 50 + } + } } ``` @@ -407,46 +406,47 @@ relative placements of various classes of buildings. ### Fields -| Identifier | Description | -| ----------------------- | ------------------------------------------------------------------ | -| `type` | City type identifier--currently unused. | -| `shop_radius` | Radial frequency of shop placement. Smaller number = more shops. | -| `park_radius` | Radial frequency of park placement. Smaller number = more parks. | -| `houses` | Weighted list of overmap terrains and specials used for houses. | -| `parks` | Weighted list of overmap terrains and specials used for parks. | -| `shops` | Weighted list of overmap terrains and specials used for shops. | +| Identifier | Description | +| ------------- | ---------------------------------------------------------------- | +| `type` | City type identifier--currently unused. | +| `shop_radius` | Radial frequency of shop placement. Smaller number = more shops. | +| `park_radius` | Radial frequency of park placement. Smaller number = more parks. | +| `houses` | Weighted list of overmap terrains and specials used for houses. | +| `parks` | Weighted list of overmap terrains and specials used for parks. | +| `shops` | Weighted list of overmap terrains and specials used for shops. | ### Placing shops, parks, and houses When picking a building to place in a given location, the game considers the city size, the location's distance from the city center, and finally the `shop_radius` and `park_radius` values for the region. It then tries to place a shop, then a park, and finally a house, where the chance to -place the shop or park are based on the formula `rng( 0, 99 ) > X_radius * distance from city center -/ city size`. +place the shop or park are based on the formula +`rng( 0, 99 ) > X_radius * distance from city center / city size`. ### Example + ```json { - "city": { - "type": "town", - "shop_radius": 80, - "park_radius": 90, - "houses": { - "house_two_story_basement": 1, - "house": 1000, - "house_base": 333, - "emptyresidentiallot": 20 - }, - "parks": { - "park": 4, - "pool": 1 - }, - "shops": { - "s_gas": 5, - "s_pharm": 3, - "s_grocery": 15 - } - } + "city": { + "type": "town", + "shop_radius": 80, + "park_radius": 90, + "houses": { + "house_two_story_basement": 1, + "house": 1000, + "house_base": 333, + "emptyresidentiallot": 20 + }, + "parks": { + "park": 4, + "pool": 1 + }, + "shops": { + "s_gas": 5, + "s_pharm": 3, + "s_grocery": 15 + } + } } ``` @@ -458,7 +458,7 @@ terrain. This includes both the chance of an extra occurring as well as the weig ### Fields -| Identifier | Description | +| Identifier | Description | | ---------- | ---------------------------------------------------------------- | | `chance` | One in X chance that the overmap terrain will spawn a map extra. | | `extras` | Weighted list of map extras that can spawn. | @@ -467,15 +467,15 @@ terrain. This includes both the chance of an extra occurring as well as the weig ```json { - "map_extras": { - "field": { - "chance": 90, - "extras": { - "mx_helicopter": 40, - "mx_portal_in": 1 - } - } - } + "map_extras": { + "field": { + "chance": 90, + "extras": { + "mx_helicopter": 40, + "mx_portal_in": 1 + } + } + } } ``` @@ -485,20 +485,19 @@ The **weather** section defines the base weather attributes used for the region. ### Fields -| Identifier | Description | -| ------------------------------ | --------------------------------------------------------------------- | -| `spring_temp` | Mid spring temperature for the region in degrees Celsius | -| `summer_temp` | Mid summer temperature for the region in degrees Celsius | -| `autumn_temp` | Mid autumn temperature for the region in degrees Celsius | -| `winter_temp` | Mid winter temperature for the region in degrees Celsius | -| `base_humidity` | Base humidity for the region in relative humidity % | -| `base_pressure` | Base pressure for the region in millibars. | -| `base_acid` | Base acid for the region in ? units. Value >= 1 is considered acidic. | -| `base_wind` | Base wind for the region in mph units. Roughly the yearly average. | -| `base_wind_distrib_peaks` | How high the wind peaks can go. Higher values produce windier days. | -| `base_wind_season_variation` | How the wind varies with season. Lower values produce more variation | -| `weather_types` | Ids of the weather types allowed in this region. First value will be the default weather type. Declaration order will affect weather selection, see [WEATHER_TYPE.md](WEATHER_TYPE.md) for details. | - +| Identifier | Description | +| ---------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| `spring_temp` | Mid spring temperature for the region in degrees Celsius | +| `summer_temp` | Mid summer temperature for the region in degrees Celsius | +| `autumn_temp` | Mid autumn temperature for the region in degrees Celsius | +| `winter_temp` | Mid winter temperature for the region in degrees Celsius | +| `base_humidity` | Base humidity for the region in relative humidity % | +| `base_pressure` | Base pressure for the region in millibars. | +| `base_acid` | Base acid for the region in ? units. Value >= 1 is considered acidic. | +| `base_wind` | Base wind for the region in mph units. Roughly the yearly average. | +| `base_wind_distrib_peaks` | How high the wind peaks can go. Higher values produce windier days. | +| `base_wind_season_variation` | How the wind varies with season. Lower values produce more variation | +| `weather_types` | Ids of the weather types allowed in this region. First value will be the default weather type. Declaration order will affect weather selection, see [WEATHER_TYPE.md](WEATHER_TYPE.md) for details. | ### Example @@ -538,12 +537,13 @@ The **weather** section defines the base weather attributes used for the region. ## Overmap Feature Flag Settings -The **overmap_feature_flag_settings** section defines operations that operate on the flags assigned to overmap features. -This is currently used to provide a mechanism for whitelisting and blacklisting locations on a per-region basis. +The **overmap_feature_flag_settings** section defines operations that operate on the flags assigned +to overmap features. This is currently used to provide a mechanism for whitelisting and blacklisting +locations on a per-region basis. ### Fields -| Identifier | Description | +| Identifier | Description | | ----------------- | ------------------------------------------------------------------------------------------ | | `clear_blacklist` | Clear all previously defined `blacklist`. | | `blacklist` | List of flags. Any location with a matching flag will be excluded from overmap generation. | @@ -554,12 +554,12 @@ This is currently used to provide a mechanism for whitelisting and blacklisting ```json { - "overmap_feature_flag_settings": { - "clear_blacklist": false, - "blacklist": [ "FUNGAL" ], - "clear_whitelist": false, - "whitelist": [] - } + "overmap_feature_flag_settings": { + "clear_blacklist": false, + "blacklist": ["FUNGAL"], + "clear_whitelist": false, + "whitelist": [] + } } ``` @@ -571,7 +571,7 @@ those values which should be changed. ### Fields -| Identifier | Description | +| Identifier | Description | | ---------- | ------------------------------------------------------------------------------------------- | | `type` | Type identifier. Must be "region_overlay". | | `id` | Unique identfier for this region overlay. | @@ -580,15 +580,16 @@ those values which should be changed. All additional fields and sections are as defined for a `region_overlay`. ### Example + ```json [{ - "type": "region_overlay", - "id": "example_overlay", - "regions": ["all"], - "city": { - "parks": { - "examplepark": 1 - } - } + "type": "region_overlay", + "id": "example_overlay", + "regions": ["all"], + "city": { + "parks": { + "examplepark": 1 + } + } }] -``` \ No newline at end of file +``` diff --git a/doc/RELICS.md b/doc/RELICS.md index d62e50bec020..b2ffb54f3397 100644 --- a/doc/RELICS.md +++ b/doc/RELICS.md @@ -7,10 +7,11 @@ Relics are regular items with special relic data attached to them. -Relic data is defined in JSON in `relic_data` field of corresponding item type definition, -and whenever the item is spawned a copy of relic data is attached to the item instance. +Relic data is defined in JSON in `relic_data` field of corresponding item type definition, and +whenever the item is spawned a copy of relic data is attached to the item instance. Relic data object can contain the following fields: + ```c++ { "name": "Boots of Haste", // Overrides default item name @@ -24,8 +25,9 @@ Relic data object can contain the following fields: ## Relic recharge -Relics can recharge under certain conditions. -Recharge method is defined as follows (all fields optional): +Relics can recharge under certain conditions. Recharge method is defined as follows (all fields +optional): + ```c++ { "type": "time", // Defines what resource is consumed. Default: time @@ -42,24 +44,24 @@ Recharge method is defined as follows (all fields optional): ### Recharge type -| ID | Description -|----------------|-------------------------------- -|`time` | Needs no additional resources -|`solar` | Consumes sunlight (character must be in sunlight) -|`pain` | Causes pain to recharge. Intensity controlled by `int_min` and `int_max` -|`hp` | Causes damage to all body parts. Intensity controlled by `int_min` and `int_max` -|`fatigue` | Causes fatigue and drains stamina. Fatigue drain controlled by `int_min` and `int_max`, stamina drain rolled as `[ int_min*100, int_max*100 ]` -|`field` | Consumes adjacent field. Allowed field intensity controlled by `int_min` and `int_max` -|`trap` | Consumes adjacent trap. +| ID | Description | +| --------- | ---------------------------------------------------------------------------------------------------------------------------------------------- | +| `time` | Needs no additional resources | +| `solar` | Consumes sunlight (character must be in sunlight) | +| `pain` | Causes pain to recharge. Intensity controlled by `int_min` and `int_max` | +| `hp` | Causes damage to all body parts. Intensity controlled by `int_min` and `int_max` | +| `fatigue` | Causes fatigue and drains stamina. Fatigue drain controlled by `int_min` and `int_max`, stamina drain rolled as `[ int_min*100, int_max*100 ]` | +| `field` | Consumes adjacent field. Allowed field intensity controlled by `int_min` and `int_max` | +| `trap` | Consumes adjacent trap. | ### Recharge requirements -| ID | Description -|----------------|-------------------------------- -|`none` | No additional requirements (always works) -|`equipped` | Must be worn if armor, wielded if weapon. -|`close_to_skin` | Must be worn underneath all other clothing, or be wielded with bare hands -|`sleep` | Character must be asleep -|`rad` | Character or map tile must be irradiated -|`wet` | Character must be wet, or it's raining -|`sky` | Character must be above z=0 +| ID | Description | +| --------------- | ------------------------------------------------------------------------- | +| `none` | No additional requirements (always works) | +| `equipped` | Must be worn if armor, wielded if weapon. | +| `close_to_skin` | Must be worn underneath all other clothing, or be wielded with bare hands | +| `sleep` | Character must be asleep | +| `rad` | Character or map tile must be irradiated | +| `wet` | Character must be wet, or it's raining | +| `sky` | Character must be above z=0 | diff --git a/doc/SOUNDPACKS.md b/doc/SOUNDPACKS.md index 25ce2c972377..6f21ca751a1b 100644 --- a/doc/SOUNDPACKS.md +++ b/doc/SOUNDPACKS.md @@ -1,10 +1,13 @@ # Soundpacks -A soundpack can be installed in the `data/sound` directory. It has to be a subdirectory that contains at least a file named `soundpack.txt`. It can include any number of json files which add any number of sound_effect or playlist. +A soundpack can be installed in the `data/sound` directory. It has to be a subdirectory that +contains at least a file named `soundpack.txt`. It can include any number of json files which add +any number of sound_effect or playlist. ## soundpack.txt format -The `soundpack.txt` file format needs 2 values, a NAME and a VIEW. The NAME value should be unique. The VIEW value will be shown in the options menu. Every line starting with a `#` is a comment line. +The `soundpack.txt` file format needs 2 values, a NAME and a VIEW. The NAME value should be unique. +The VIEW value will be shown in the options menu. Every line starting with a `#` is a comment line. ``` #Basic provided soundpack @@ -21,235 +24,262 @@ VIEW: Basic Sound effects can be included with a format like this: ```javascript -[ - { - "type": "sound_effect", - "id" : "menu_move", - "volume" : 100, - "files" : [ - "nenadsimic_menu_selection_click.wav" - ] - }, - { - "type": "sound_effect", - "id" : "fire_gun", - "volume" : 90, - "variant" : "bio_laser_gun", - "files" : [ - "guns/energy_generic/weapon_fire_laser.ogg" - ] - } +;[ + { + "type": "sound_effect", + "id": "menu_move", + "volume": 100, + "files": [ + "nenadsimic_menu_selection_click.wav", + ], + }, + { + "type": "sound_effect", + "id": "fire_gun", + "volume": 90, + "variant": "bio_laser_gun", + "files": [ + "guns/energy_generic/weapon_fire_laser.ogg", + ], + }, ] ``` -Adding variety: If for a certain `id`'s `variant` multiple `files` are defined, they will be chosen at random when `variant` is played. + +Adding variety: If for a certain `id`'s `variant` multiple `files` are defined, they will be chosen +at random when `variant` is played. The volume key may range from 0-100. -Cataclysm has its own set of user-controllable volumes that will additionally affect the sound. These range from 0-128, and the default is 100. This means that at default volume, any sound that Cataclysm plays will default to playing at about 78% of the maximum; if you are working on sounds in an external audio editor, expect Cataclysm at default volume settings to play that sound file back more-quietly than your editor does. +Cataclysm has its own set of user-controllable volumes that will additionally affect the sound. +These range from 0-128, and the default is 100. This means that at default volume, any sound that +Cataclysm plays will default to playing at about 78% of the maximum; if you are working on sounds in +an external audio editor, expect Cataclysm at default volume settings to play that sound file back +more-quietly than your editor does. ### Preloading SFX Sound effects can be included for preloading with a format like this: ```javascript -[ - { - "type": "sound_effect_preload", - "preload": [ - { "id": "environment", "variant": "daytime" }, - { "id": "environment" } - ] - } +;[ + { + "type": "sound_effect_preload", + "preload": [ + { "id": "fire_gun", "variant": "all" }, + { "id": "environment", "variant": "daytime" }, + { "id": "environment" }, + ], + }, ] ``` +`"variant": "all"` will be treated specially and load all variants of the given id. + +> [!WARNING] `"variant": "all"` uses unoptimal algorithm (because the devs were dumb and lazy and +> used hacks) and will slow down game loading time. + +If `"variant"` is omitted, it defaults to `"default"`. + ### Playlist A playlist can be included with a format like this: ```javascript -[ - { - "type": "playlist", - "playlists": - [ - { - "id" : "title", - "shuffle" : false, - "files" : [ - { - "file": "Dark_Days_Ahead_demo_2.wav", - "volume": 100 - }, - { - "file": "cataclysmthemeREV6.wav", - "volume": 90 - } - ] - } - ] - } +;[ + { + "type": "playlist", + "playlists": [ + { + "id": "title", + "shuffle": false, + "files": [ + { + "file": "Dark_Days_Ahead_demo_2.wav", + "volume": 100, + }, + { + "file": "cataclysmthemeREV6.wav", + "volume": 90, + }, + ], + }, + ], + }, ] ``` -Each sound effect is identified by an id and a variant. If a sound effect is played with a variant that does not exist in the json files, but a variant "default" exists, then the "default" variant is played instead. The file name of the sound effect is relative to the soundpack directory, so if the file name is set to "sfx.wav" and your soundpack is in `data/sound/mypack`, the file must be placed at `data/sound/mypack/sfx.wav`. +Each sound effect is identified by an id and a variant. If a sound effect is played with a variant +that does not exist in the json files, but a variant "default" exists, then the "default" variant is +played instead. The file name of the sound effect is relative to the soundpack directory, so if the +file name is set to "sfx.wav" and your soundpack is in `data/sound/mypack`, the file must be placed +at `data/sound/mypack/sfx.wav`. ## JSON Format Sound Effects List -A full list of sound effect id's and variants is given in the following. Each line in the list has the following format: +A full list of sound effect id's and variants is given in the following. Each line in the list has +the following format: `id variant1|variant2` -Where id describes the id of the sound effect, and a list of variants separated by | follows. When the variants are omitted, the variant "default" is assumed. Where the variants do not represent literal strings, but variables, they will be enclosed in `<` `>`. For instance, `` is a placeholder for any valid furniture ID (as in the furniture definition JSON). +Where id describes the id of the sound effect, and a list of variants separated by | follows. When +the variants are omitted, the variant "default" is assumed. Where the variants do not represent +literal strings, but variables, they will be enclosed in `<` `>`. For instance, `` is a +placeholder for any valid furniture ID (as in the furniture definition JSON). # open/close doors -* `open_door default||` -* `close_door default||` - - # smashing attempts and results, few special ones and furniture/terrain specific -* `bash default` -* `smash wall|door|door_boarded|glass|swing|web|paper_torn|metal` -* `smash_success hit_vehicle|smash_glass_contents|smash_cloth||` -* `smash_fail default||` - - # melee sounds -* `melee_swing default|small_bash|small_cutting|small_stabbing|big_bash|big_cutting|big_stabbing` -* `melee_hit_flesh default|small_bash|small_cutting|small_stabbing|big_bash|big_cutting|big_stabbing|` -* `melee_hit_metal default|small_bash|small_cutting|small_stabbing|big_bash|big_cutting|big_stabbing!` -* `melee_hit ` # note: use weapon id "null" for unarmed attacks - - # firearm/ranged weapon sounds -* `fire_gun |brass_eject|empty` -* `fire_gun_distant ` -* `reload ` -* `bullet_hit hit_flesh|hit_wall|hit_metal|hit_glass|hit_water` - - # environmental sfx, here divided by sections for clarity -* `environment thunder_near|thunder_far` -* `environment daytime|nighttime` -* `environment indoors|indoors_rain|underground` -* `environment ` # examples: `WEATHER_DRIZZLE|WEATHER_RAINY|WEATHER_THUNDER|WEATHER_FLURRIES|WEATHER_SNOW|WEATHER_SNOWSTORM` -* `environment alarm|church_bells|police_siren` -* `environment deafness_shock|deafness_tone_start|deafness_tone_light|deafness_tone_medium|deafness_tone_heavy` - - # misc environmental sounds -* `footstep default|light|clumsy|bionic` -* `explosion default|small|huge` - - # ambient danger theme for seeing large numbers of zombies -* `danger_low` -* `danger_medium` -* `danger_high` -* `danger_extreme` - - # chainsaw pack -* `chainsaw_cord chainsaw_on` -* `chainsaw_start chainsaw_on` -* `chainsaw_start chainsaw_on` -* `chainsaw_stop chainsaw_on` -* `chainsaw_idle chainsaw_on` -* `melee_swing_start chainsaw_on` -* `melee_swing_end chainsaw_on` -* `melee_swing chainsaw_on` -* `melee_hit_flesh chainsaw_on` -* `melee_hit_metal chainsaw_on` -* `weapon_theme chainsaw` - - # monster death and bite attacks -* `mon_death zombie_death|zombie_gibbed` -* `mon_bite bite_miss|bite_hit` - -* `melee_attack monster_melee_hit` - -* `player_laugh laugh_f|laugh_m` - - # player movement sfx - important: `plmove ` has priority over default `plmove|walk_` (excluding `|barefoot`) - example: if `plmove|t_grass_long` is defined it will be played before default `plmove|walk_grass` default for all grassy terrains - -* `plmove |` -* `plmove walk_grass|walk_dirt|walk_metal|walk_water|walk_tarmac|walk_barefoot|clear_obstacle` - - # fatigue -* `plmove fatigue_m_low|fatigue_m_med|fatigue_m_high|fatigue_f_low|fatigue_f_med|fatigue_f_high` - - # player hurt sounds -* `deal_damage hurt_f|hurt_m` - - # player death and end-game sounds -* `clean_up_at_end game_over|death_m|death_f` - - # variuos bionic sounds -* `bionic elec_discharge|elec_crackle_low|elec_crackle_med|elec_crackle_high|elec_blast|elec_blast_muffled|acid_discharge|pixelated` -* `bionic bio_resonator|bio_hydraulics|` - - # various tools/traps being used (including some associated terrain/furniture) -* `tool alarm_clock|jackhammer|pickaxe|oxytorch|hacksaw|axe|shovel|crowbar|boltcutters|compactor|gaspump|noise_emitter|repair_kit|camera_shutter|handcuffs` -* `tool geiger_low|geiger_medium|geiger_high` -* `trap bubble_wrap|bear_trap|snare|teleport|dissector|glass_caltrop|glass` - - # various activities -* `activity burrow` - - # musical instruments, `_bad` is used when you fail to play it well -* `musical_instrument ` -* `musical_instrument_bad ` - - # various shouts and screams -* `shout default|scream|scream_tortured|roar|squeak|shriek|wail|howl` - - # speach, it is currently linked with either item or monster id, or is special `NPC` or `NPC_loud` - # TODO: full vocalization of speech.json -* `speech ` # examples: talking_doll, creepy_doll, Granade, -* `speech ` # examples: eyebot, minitank, mi-go, many robots -* `speech NPC_m|NPC_f|NPC_m_loud|NPC_f_loud` # special for NPCs -* `speech robot` # special for robotic voice from a machine etc. - - # radio chatter -* `radio static|inaudible_chatter` - - # humming sounds of various origin -* `humming electric|machinery` - - # sounds related to (burning) fire -* `fire ignition` - - # vehicle sounds - engine and other parts in action - # note: defaults are executed when specific option is not defined -* `engine_start ` # note: specific engine start (id of any engine/motor/steam_engine/paddle/oar/sail/etc. ) -* `engine_start combustion|electric|muscle|wind` # default engine starts groups -* `engine_stop ` # note: specific engine stop (id of any engine/motor/steam_engine/paddle/oar/sail/etc. ) -* `engine_stop combustion|electric|muscle|wind` # default engine stop groups - - # note: internal engine sound is dynamically pitch shifted depending on vehicle speed - # it is an ambient looped sound with dedicated channel -* `engine_working_internal ` # note: sound of engine working heard inside vehicle -* `engine_working_internal combustion|electric|muscle|wind` # default engine working (inside) groups - - # note: external engine sound volume and pan is dynamically shifted depending on distance and angle to vehicle - # volume heard at given distance is linked to engine's `noise_factor` and stress to the engine (see `vehicle::noise_and_smoke()` ) - # it is an ambient looped sound with dedicated channel - # this is a single-channel solution (TODO: multi-channel for every heard vehicle); it picks loudest heard vehicle - # there is no pitch shift here (may be introduced when need for it emerges) -* `engine_working_external ` # note: sound of engine working heard outside vehicle -* `engine_working_external combustion|electric|muscle|wind` # default engine working (outside) groups - - # note: gear_up/gear_down is done automatically by pitch manipulation - # gear shift is dependant on max safe speed, and works in assumption, that there are - # 6 forward gears, gear 0 = neutral, and gear -1 = reverse -* `vehicle gear_shift` - - -* `vehicle engine_backfire|engine_bangs_start|fault_immobiliser_beep|engine_single_click_fail|engine_multi_click_fail|engine_stutter_fail|engine_clanking_fail` -* `vehicle horn_loud|horn_medium|horn_low|rear_beeper|chimes|car_alarm` -* `vehicle reaper|scoop|scoop_thump` - -* `vehicle_open ` # note: id of: doors, trunks, hatches, etc. -* `vehicle_close ` - - # miscellaneous sounds -* `misc flashbang|flash|shockwave|earthquake|stairs_movement|stones_grinding|bomb_ticking|lit_fuse|cow_bell|bell|timber` -* `misc rc_car_hits_obstacle|rc_car_drives` -* `misc default|whistle|airhorn|horn_bicycle|servomotor` -* `misc beep|ding|` -* `misc rattling|spitting|coughing|heartbeat|puff|inhale|exhale|insect_wings|snake_hiss` # mostly organic noises + +- `open_door default||` +- `close_door default||` + + # smashing attempts and results, few special ones and furniture/terrain specific +- `bash default` +- `smash wall|door|door_boarded|glass|swing|web|paper_torn|metal` +- `smash_success hit_vehicle|smash_glass_contents|smash_cloth||` +- `smash_fail default||` + + # melee sounds +- `melee_swing default|small_bash|small_cutting|small_stabbing|big_bash|big_cutting|big_stabbing` +- `melee_hit_flesh default|small_bash|small_cutting|small_stabbing|big_bash|big_cutting|big_stabbing|` +- `melee_hit_metal default|small_bash|small_cutting|small_stabbing|big_bash|big_cutting|big_stabbing!` +- `melee_hit ` # note: use weapon id "null" for unarmed attacks + + # firearm/ranged weapon sounds +- `fire_gun |brass_eject|empty` +- `fire_gun_distant ` +- `reload ` +- `bullet_hit hit_flesh|hit_wall|hit_metal|hit_glass|hit_water` + + # environmental sfx, here divided by sections for clarity +- `environment thunder_near|thunder_far` +- `environment daytime|nighttime` +- `environment indoors|indoors_rain|underground` +- `environment ` # examples: + `WEATHER_DRIZZLE|WEATHER_RAINY|WEATHER_THUNDER|WEATHER_FLURRIES|WEATHER_SNOW|WEATHER_SNOWSTORM` +- `environment alarm|church_bells|police_siren` +- `environment deafness_shock|deafness_tone_start|deafness_tone_light|deafness_tone_medium|deafness_tone_heavy` + + # misc environmental sounds +- `footstep default|light|clumsy|bionic` +- `explosion default|small|huge` + + # ambient danger theme for seeing large numbers of zombies +- `danger_low` +- `danger_medium` +- `danger_high` +- `danger_extreme` + + # chainsaw pack +- `chainsaw_cord chainsaw_on` +- `chainsaw_start chainsaw_on` +- `chainsaw_start chainsaw_on` +- `chainsaw_stop chainsaw_on` +- `chainsaw_idle chainsaw_on` +- `melee_swing_start chainsaw_on` +- `melee_swing_end chainsaw_on` +- `melee_swing chainsaw_on` +- `melee_hit_flesh chainsaw_on` +- `melee_hit_metal chainsaw_on` +- `weapon_theme chainsaw` + + # monster death and bite attacks +- `mon_death zombie_death|zombie_gibbed` +- `mon_bite bite_miss|bite_hit` + +- `melee_attack monster_melee_hit` + +- `player_laugh laugh_f|laugh_m` + + # player movement sfx + important: `plmove ` has priority over default `plmove|walk_` (excluding + `|barefoot`) example: if `plmove|t_grass_long` is defined it will be played before default + `plmove|walk_grass` default for all grassy terrains + +- `plmove |` +- `plmove walk_grass|walk_dirt|walk_metal|walk_water|walk_tarmac|walk_barefoot|clear_obstacle` + + # fatigue +- `plmove fatigue_m_low|fatigue_m_med|fatigue_m_high|fatigue_f_low|fatigue_f_med|fatigue_f_high` + + # player hurt sounds +- `deal_damage hurt_f|hurt_m` + + # player death and end-game sounds +- `clean_up_at_end game_over|death_m|death_f` + + # variuos bionic sounds +- `bionic elec_discharge|elec_crackle_low|elec_crackle_med|elec_crackle_high|elec_blast|elec_blast_muffled|acid_discharge|pixelated` +- `bionic bio_resonator|bio_hydraulics|` + + # various tools/traps being used (including some associated terrain/furniture) +- `tool alarm_clock|jackhammer|pickaxe|oxytorch|hacksaw|axe|shovel|crowbar|boltcutters|compactor|gaspump|noise_emitter|repair_kit|camera_shutter|handcuffs` +- `tool geiger_low|geiger_medium|geiger_high` +- `trap bubble_wrap|bear_trap|snare|teleport|dissector|glass_caltrop|glass` + + # various activities +- `activity burrow` + + # musical instruments, `_bad` is used when you fail to play it well +- `musical_instrument ` +- `musical_instrument_bad ` + + # various shouts and screams +- `shout default|scream|scream_tortured|roar|squeak|shriek|wail|howl` + + # speach, it is currently linked with either item or monster id, or is special `NPC` or `NPC_loud` + # TODO: full vocalization of speech.json +- `speech ` # examples: talking_doll, creepy_doll, Granade, +- `speech ` # examples: eyebot, minitank, mi-go, many robots +- `speech NPC_m|NPC_f|NPC_m_loud|NPC_f_loud` # special for NPCs +- `speech robot` # special for robotic voice from a machine etc. + + # radio chatter +- `radio static|inaudible_chatter` + + # humming sounds of various origin +- `humming electric|machinery` + + # sounds related to (burning) fire +- `fire ignition` + + # vehicle sounds - engine and other parts in action + # note: defaults are executed when specific option is not defined +- `engine_start ` # note: specific engine start (id of any + engine/motor/steam_engine/paddle/oar/sail/etc. ) +- `engine_start combustion|electric|muscle|wind` # default engine starts groups +- `engine_stop ` # note: specific engine stop (id of any + engine/motor/steam_engine/paddle/oar/sail/etc. ) +- `engine_stop combustion|electric|muscle|wind` # default engine stop groups + + # note: internal engine sound is dynamically pitch shifted depending on vehicle speed + # it is an ambient looped sound with dedicated channel +- `engine_working_internal ` # note: sound of engine working heard inside vehicle +- `engine_working_internal combustion|electric|muscle|wind` # default engine working (inside) groups + + # note: external engine sound volume and pan is dynamically shifted depending on distance and angle to vehicle + # volume heard at given distance is linked to engine's `noise_factor` and stress to the engine (see `vehicle::noise_and_smoke()` ) + # it is an ambient looped sound with dedicated channel + # this is a single-channel solution (TODO: multi-channel for every heard vehicle); it picks loudest heard vehicle + # there is no pitch shift here (may be introduced when need for it emerges) +- `engine_working_external ` # note: sound of engine working heard outside vehicle +- `engine_working_external combustion|electric|muscle|wind` # default engine working (outside) + groups + + # note: gear_up/gear_down is done automatically by pitch manipulation + # gear shift is dependant on max safe speed, and works in assumption, that there are + # 6 forward gears, gear 0 = neutral, and gear -1 = reverse +- `vehicle gear_shift` + +- `vehicle engine_backfire|engine_bangs_start|fault_immobiliser_beep|engine_single_click_fail|engine_multi_click_fail|engine_stutter_fail|engine_clanking_fail` +- `vehicle horn_loud|horn_medium|horn_low|rear_beeper|chimes|car_alarm` +- `vehicle reaper|scoop|scoop_thump` + +- `vehicle_open ` # note: id of: doors, trunks, hatches, etc. +- `vehicle_close ` + + # miscellaneous sounds +- `misc flashbang|flash|shockwave|earthquake|stairs_movement|stones_grinding|bomb_ticking|lit_fuse|cow_bell|bell|timber` +- `misc rc_car_hits_obstacle|rc_car_drives` +- `misc default|whistle|airhorn|horn_bicycle|servomotor` +- `misc beep|ding|` +- `misc rattling|spitting|coughing|heartbeat|puff|inhale|exhale|insect_wings|snake_hiss` # mostly + organic noises diff --git a/doc/TER_FURN_TRANSFORM.md b/doc/TER_FURN_TRANSFORM.md index 043a68df950d..5cfd6f9e9688 100644 --- a/doc/TER_FURN_TRANSFORM.md +++ b/doc/TER_FURN_TRANSFORM.md @@ -1,6 +1,7 @@ # ter_furn_transform -A ter_furn_transform is a type of json object that allows you to specify a transformation of a tile from one terrain to another terrain, and from one furniture to another furniture. +A ter_furn_transform is a type of json object that allows you to specify a transformation of a tile +from one terrain to another terrain, and from one furniture to another furniture. ```json [ @@ -10,7 +11,7 @@ A ter_furn_transform is a type of json object that allows you to specify a trans "terrain": [ { "result": "t_dirt", - "valid_terrain": [ "t_sand" ], + "valid_terrain": ["t_sand"], "message": "sandy!", "message_good": true } @@ -19,8 +20,9 @@ A ter_furn_transform is a type of json object that allows you to specify a trans ] ``` -The example above turns "sand" into "dirt". It does so by comparing the direct terrain ids. In addition, we can add a fail message to the transform. -If, however, we wanted to turn sand into "dirt or grass" we can do: +The example above turns "sand" into "dirt". It does so by comparing the direct terrain ids. In +addition, we can add a fail message to the transform. If, however, we wanted to turn sand into "dirt +or grass" we can do: ```json "terrain": [ @@ -33,8 +35,8 @@ If, however, we wanted to turn sand into "dirt or grass" we can do: ] ``` -message_good is optional and defaults to true. -This example chooses either dirt or grass at a 1:1 ratio. But, if you want a 4:1 ratio: +message_good is optional and defaults to true. This example chooses either dirt or grass at a 1:1 +ratio. But, if you want a 4:1 ratio: ```json "terrain": [ @@ -46,7 +48,8 @@ This example chooses either dirt or grass at a 1:1 ratio. But, if you want a 4:1 ] ``` -As you can see, you can mix and match arrays with weights with single strings. Each single string has a weight of 1. +As you can see, you can mix and match arrays with weights with single strings. Each single string +has a weight of 1. All of the above applies to furniture as well. @@ -72,4 +75,5 @@ You can also use flags instead of specific IDs for both furniture and terrain. ] ``` -A ter_furn_transform can have both terrain and furniture fields. It treats them separately, so no "if dirt, add chair." +A ter_furn_transform can have both terrain and furniture fields. It treats them separately, so no +"if dirt, add chair." diff --git a/doc/TESTING.md b/doc/TESTING.md index 7fc661d7636a..9cbdeaf8b93f 100644 --- a/doc/TESTING.md +++ b/doc/TESTING.md @@ -1,47 +1,42 @@ # Testing Cataclysm -When you `make` Cataclysm from source, an executable `tests/cata_test` is built -from test cases found in the `tests/` directory. These tests are written in the +When you `make` Cataclysm from source, an executable `tests/cata_test` is built from test cases +found in the `tests/` directory. These tests are written in the [Catch2 framework](https://github.com/catchorg/Catch2). -Run `tests/cata_test --help` to see the available command-line options, and/or -consult the [Catch2 tutorial](https://github.com/catchorg/Catch2/blob/master/docs/tutorial.md) -for a more thorough introduction. - +Run `tests/cata_test --help` to see the available command-line options, and/or consult the +[Catch2 tutorial](https://github.com/catchorg/Catch2/blob/master/docs/tutorial.md) for a more +thorough introduction. ## Guidelines -When creating tests, ensure that all objects used (directly or indirectly) are -fully reset before testing. Several tests have been rendered flaky by -properties of randomly generated objects or interactions between tests via -global objects (often the player object). As a general guideline, test cases -should be standalone (one test should not rely on the output of another). - -When generating objects with json definitions, use REQUIRE statements to assert -the properties of the objects that the test needs. This protects the test from -shifting json definitions by making it apparent what about the object changed -to cause the test to break. +When creating tests, ensure that all objects used (directly or indirectly) are fully reset before +testing. Several tests have been rendered flaky by properties of randomly generated objects or +interactions between tests via global objects (often the player object). As a general guideline, +test cases should be standalone (one test should not rely on the output of another). +When generating objects with json definitions, use REQUIRE statements to assert the properties of +the objects that the test needs. This protects the test from shifting json definitions by making it +apparent what about the object changed to cause the test to break. ## Writing test cases -You can choose several ways to organize and express your tests, but the basic -unit is a `TEST_CASE`. Each test `.cpp` file should define at least one test -case, with a name, and optional (but strongly encouraged) list of tags: +You can choose several ways to organize and express your tests, but the basic unit is a `TEST_CASE`. +Each test `.cpp` file should define at least one test case, with a name, and optional (but strongly +encouraged) list of tags: ```cpp - TEST_CASE( "sweet junk food", "[food][junk][sweet]" ) - { - // ... - } +TEST_CASE( "sweet junk food", "[food][junk][sweet]" ) +{ + // ... +} ``` -Within the `TEST_CASE`, the Catch2 framework allows a number of different -macros for logically grouping related parts of the test together. One approach -that encourages a high level of readability is the -[BDD](https://en.wikipedia.org/wiki/Behavior-driven_development) -(behavior-driven-development) style using `GIVEN`, `WHEN`, and `THEN` sections. -Here's an outline of what a test might look like using those: +Within the `TEST_CASE`, the Catch2 framework allows a number of different macros for logically +grouping related parts of the test together. One approach that encourages a high level of +readability is the [BDD](https://en.wikipedia.org/wiki/Behavior-driven_development) +(behavior-driven-development) style using `GIVEN`, `WHEN`, and `THEN` sections. Here's an outline of +what a test might look like using those: ```cpp TEST_CASE( "sweet junk food", "[food][junk][sweet]" ) @@ -57,11 +52,10 @@ Here's an outline of what a test might look like using those: } ``` -Thinking in these terms may help you understand the logical progression from -setting up the test and initializing the test data (usually expressed by the -`GIVEN` part), performing some operation that generates a result you want to -test (often contained in the `WHEN` part), and verifying this result meets your -expectations (the `THEN` part, naturally). +Thinking in these terms may help you understand the logical progression from setting up the test and +initializing the test data (usually expressed by the `GIVEN` part), performing some operation that +generates a result you want to test (often contained in the `WHEN` part), and verifying this result +meets your expectations (the `THEN` part, naturally). Filling in the above with actual test code might look like this: @@ -86,76 +80,70 @@ Filling in the above with actual test code might look like this: } ``` -Let's look at each part in turn to see what's going on. First, we declare an -`avatar`, representing the character or player. This test is going to check the -player's morale, so we clear it to ensure a clean slate: +Let's look at each part in turn to see what's going on. First, we declare an `avatar`, representing +the character or player. This test is going to check the player's morale, so we clear it to ensure a +clean slate: ```cpp - avatar dummy; - dummy.clear_morale(); +avatar dummy; +dummy.clear_morale(); ``` -Inside the `GIVEN`, we want some code that implements what the `GIVEN` is -saying - that the character has a sweet tooth. In the game's code, this is -represented with the `PROJUNK` trait, so we can set that using `toggle_trait`: +Inside the `GIVEN`, we want some code that implements what the `GIVEN` is saying - that the +character has a sweet tooth. In the game's code, this is represented with the `PROJUNK` trait, so we +can set that using `toggle_trait`: ```cpp - GIVEN( "character has a sweet tooth" ) { - dummy.toggle_trait( trait_PROJUNK ); +GIVEN( "character has a sweet tooth" ) { + dummy.toggle_trait( trait_PROJUNK ); ``` -Now, notice we are nested inside the `GIVEN` - for the rest of the scope of -that `GIVEN`, the `dummy` will have this trait. For this simple test it will -only affect a couple more lines, but when your tests become larger and more -complex (which they will), you will need to be aware of these nested scopes and -how you can use them to avoid cross-pollution between your tests. +Now, notice we are nested inside the `GIVEN` - for the rest of the scope of that `GIVEN`, the +`dummy` will have this trait. For this simple test it will only affect a couple more lines, but when +your tests become larger and more complex (which they will), you will need to be aware of these +nested scopes and how you can use them to avoid cross-pollution between your tests. -Anyway, now that our `dummy` has a sweet tooth, we want them to eat something -sweet, so we can spawn the `neccowafers` item and tell them to eat some: +Anyway, now that our `dummy` has a sweet tooth, we want them to eat something sweet, so we can spawn +the `neccowafers` item and tell them to eat some: ```cpp - WHEN( "they eat some junk food" ) { - dummy.eat( item( "neccowafers" ) ); +WHEN( "they eat some junk food" ) { + dummy.eat( item( "neccowafers" ) ); ``` -The function(s) you invoke at this point are often the focus of your testing; -the goal is to exercise some pathway through those function(s) in such a way -that your code will be reached, and thus covered by the test. The `eat` -function is used as an example here, but that is quite a high-level, complex -function itself, with many behaviors and sub-behaviors. Since this test case is -only interested in the morale effect, a better test would invoke a lower-level -function that `eat` invokes, such as `modify_morale`. +The function(s) you invoke at this point are often the focus of your testing; the goal is to +exercise some pathway through those function(s) in such a way that your code will be reached, and +thus covered by the test. The `eat` function is used as an example here, but that is quite a +high-level, complex function itself, with many behaviors and sub-behaviors. Since this test case is +only interested in the morale effect, a better test would invoke a lower-level function that `eat` +invokes, such as `modify_morale`. -Our `dummy` has eaten the `neccowafers`, but did it do anything? Because they -have a sweet tooth, they should get a specific morale bonus known as -`MORALE_SWEETTOOTH`, and it should be at least `5` in magnitude: +Our `dummy` has eaten the `neccowafers`, but did it do anything? Because they have a sweet tooth, +they should get a specific morale bonus known as `MORALE_SWEETTOOTH`, and it should be at least `5` +in magnitude: ```cpp - THEN( "they get a morale bonus from its sweetness" ) { - CHECK( dummy.has_morale( MORALE_SWEETTOOTH ) >= 5 ); - } +THEN( "they get a morale bonus from its sweetness" ) { + CHECK( dummy.has_morale( MORALE_SWEETTOOTH ) >= 5 ); +} ``` -This `CHECK` macro takes a boolean expression, failing the test if the -expression is false. Likewise, you can use `CHECK_FALSE`, which will fail if -the expression is true. - +This `CHECK` macro takes a boolean expression, failing the test if the expression is false. +Likewise, you can use `CHECK_FALSE`, which will fail if the expression is true. ## Requiring or Checking -While the `CHECK` and `CHECK_FALSE` macros make assertions about the truth or -falsity of expressions, they still allow the test to continue, even when they -fail. This lets you do several `CHECK`s, and be informed if one *or more* of -them do not meet your expectations. +While the `CHECK` and `CHECK_FALSE` macros make assertions about the truth or falsity of +expressions, they still allow the test to continue, even when they fail. This lets you do several +`CHECK`s, and be informed if one _or more_ of them do not meet your expectations. -Another kind of assertion is the `REQUIRE` (and its counterpart -`REQUIRE_FALSE`). Unlike the `CHECK` assertions, `REQUIRE` will not continue if -it fails - this assertion is considered essential for the test to continue. +Another kind of assertion is the `REQUIRE` (and its counterpart `REQUIRE_FALSE`). Unlike the `CHECK` +assertions, `REQUIRE` will not continue if it fails - this assertion is considered essential for the +test to continue. -A `REQUIRE` is useful when you wish to double-check your assumptions after -making some change to the system state. For example, here are a couple of -`REQUIRE`s added to the sweet-tooth test, to ensure our `dummy` really has the -desired trait, and that the `neccowafers` really are junk food: +A `REQUIRE` is useful when you wish to double-check your assumptions after making some change to the +system state. For example, here are a couple of `REQUIRE`s added to the sweet-tooth test, to ensure +our `dummy` really has the desired trait, and that the `neccowafers` really are junk food: ```cpp GIVEN( "character has a sweet tooth" ) { @@ -175,11 +163,10 @@ desired trait, and that the `neccowafers` really are junk food: } ``` -We use `REQUIRE` here, because there is no reason to continue the test if these -fail. If our assumptions are wrong, nothing that follows is valid. Clearly, if -`toggle_trait` failed to give the character the `PROJUNK` trait, or if the -`neccowafers` turn out not to be made of sugar after all, then our test of the -morale bonus is meaningless. +We use `REQUIRE` here, because there is no reason to continue the test if these fail. If our +assumptions are wrong, nothing that follows is valid. Clearly, if `toggle_trait` failed to give the +character the `PROJUNK` trait, or if the `neccowafers` turn out not to be made of sugar after all, +then our test of the morale bonus is meaningless. -You can think of `REQUIRE` as being a prerequisite for the test, while `CHECK` -is looking at the results of the test. +You can think of `REQUIRE` as being a prerequisite for the test, while `CHECK` is looking at the +results of the test. diff --git a/doc/TILESET.md b/doc/TILESET.md index 51dc6136ed09..0d04cddda02a 100644 --- a/doc/TILESET.md +++ b/doc/TILESET.md @@ -1,39 +1,78 @@ # TILESETS -A tileset provides graphic images for the game. Each tileset has one or more tilesheets of image sprites and a `tile_config.json` file that describes how to map the contents of the sprite sheets to various entities in the game. It also has a `tileset.txt` file that provides metadata. + +A tileset provides graphic images for the game. Each tileset has one or more tilesheets of image +sprites and a `tile_config.json` file that describes how to map the contents of the sprite sheets to +various entities in the game. It also has a `tileset.txt` file that provides metadata. ## Compositing Tilesets -Prior October 2019, tilesets had to be submitted to the repo with each tilesheet fully composited and the sprite indices in `tile_config.json` calculated by hand. After October 2019, tilesets can be submitted to repos as directories of individual sprite files and tile entry JSON files that used sprite file names, and a Python script that runs at compile time would merge the sprite images into tilesheets, convert the files names into sprite indices for the tile entries, and merge the tile entries into a `tile_config.json`. -For the rest of this document, tilesets that are submitted as fully composited tilesheets are called legacy tilesets, and tilesets that submitted as individual sprite image files are compositing tilesets. +Prior October 2019, tilesets had to be submitted to the repo with each tilesheet fully composited +and the sprite indices in `tile_config.json` calculated by hand. After October 2019, tilesets can be +submitted to repos as directories of individual sprite files and tile entry JSON files that used +sprite file names, and a Python script that runs at compile time would merge the sprite images into +tilesheets, convert the files names into sprite indices for the tile entries, and merge the tile +entries into a `tile_config.json`. + +For the rest of this document, tilesets that are submitted as fully composited tilesheets are called +legacy tilesets, and tilesets that submitted as individual sprite image files are compositing +tilesets. ### tools/gfx_tools/decompose.py -This is a Python script that will convert a legacy tileset into a compositing tileset. It reads the `tile_config.json` and assigns semi-arbitrary file names to each sprite index. Then it changes all the sprite indexes references to the file names. Then it breaks up `tile_config.json` into many small tile_entry JSON files with arbitrary file names, and pulls out each sprite and writes it to aseparate file. + +This is a Python script that will convert a legacy tileset into a compositing tileset. It reads the +`tile_config.json` and assigns semi-arbitrary file names to each sprite index. Then it changes all +the sprite indexes references to the file names. Then it breaks up `tile_config.json` into many +small tile_entry JSON files with arbitrary file names, and pulls out each sprite and writes it to +aseparate file. It requires pyvips to do the image processing. -It takes a single mandatory argument, which is the path to the tileset directory. For example: -`python tools/gfx_tools/decompose.py gfx/ChestHole16Tileset` will convert the legacy ChestHole16 tileset to a compositing tileset. +It takes a single mandatory argument, which is the path to the tileset directory. For example: +`python tools/gfx_tools/decompose.py gfx/ChestHole16Tileset` will convert the legacy ChestHole16 +tileset to a compositing tileset. -decompose.py creates a sufficient directory hierarchy and file names for a tileset to be compositing, but it is machine generated and badly organized. New compositing tilesets should use more sensible file names and a better organization. +decompose.py creates a sufficient directory hierarchy and file names for a tileset to be +compositing, but it is machine generated and badly organized. New compositing tilesets should use +more sensible file names and a better organization. -It shouldn't be necessary to run decompose.py very often. Legacy tilesets should only need to be converted to composite tilesets one time. +It shouldn't be necessary to run decompose.py very often. Legacy tilesets should only need to be +converted to composite tilesets one time. ### tools/gfx_tools/compose.py -This is a Python script that creates the tilesheets for a compositing tileset. It reads all of the directories in a tileset's directory with names that start with `pngs_` for sprite files and `tile_entry` JSON files, creates mappings of sprite file names to indices, merges the sprite files into tilesheets, changes all of the sprite file name references in the `tile_entries` to indices, and merges the `tile_entries` into a `tile_config.json`. + +This is a Python script that creates the tilesheets for a compositing tileset. It reads all of the +directories in a tileset's directory with names that start with `pngs_` for sprite files and +`tile_entry` JSON files, creates mappings of sprite file names to indices, merges the sprite files +into tilesheets, changes all of the sprite file name references in the `tile_entries` to indices, +and merges the `tile_entries` into a `tile_config.json`. Like decompose.py, it requires pyvips to the image processing. The original sprite files and `tile_entry` JSON files are preserved. ### directory structure -Each compositing tileset has one or more directories in it with a name that starts with `pngs_`, such as `pngs_tree_32x40` or `pngs_overlay`. These are the image directories. All of the sprites in an image directory must have the same height and width and will be merged into a single tilesheet. -It is recommended that tileset developers include the sprite dimensions in the image directory name, but this is not required. `pngs_overlay_24x24` is preferred over `pngs_overlay` but both are allowed. As each image directory creates its own tilesheet, and tilesheets should be as large as possible for performance reasons, tileset developers are strongly encouraged to minimize the number of image directories. +Each compositing tileset has one or more directories in it with a name that starts with `pngs_`, +such as `pngs_tree_32x40` or `pngs_overlay`. These are the image directories. All of the sprites in +an image directory must have the same height and width and will be merged into a single tilesheet. + +It is recommended that tileset developers include the sprite dimensions in the image directory name, +but this is not required. `pngs_overlay_24x24` is preferred over `pngs_overlay` but both are +allowed. As each image directory creates its own tilesheet, and tilesheets should be as large as +possible for performance reasons, tileset developers are strongly encouraged to minimize the number +of image directories. -Each image directory contains a hierarchy of subdirectories, `tile_entry` JSON files, and sprite files. There is no restriction on the arrangement or names of these files, except for `tile_entry` JSON files for expansion tilesheets must be at the top level of the image directory. Subdirectories are not required but are recommended to keep things manageable. +Each image directory contains a hierarchy of subdirectories, `tile_entry` JSON files, and sprite +files. There is no restriction on the arrangement or names of these files, except for `tile_entry` +JSON files for expansion tilesheets must be at the top level of the image directory. Subdirectories +are not required but are recommended to keep things manageable. #### `tile_entry` JSON -Each `tile_entry` JSON is a dictionary that describes how to map one or more game entities to one or more sprites. The simplest version has a single game entity, a single foreground sprite, an *optional* background sprite, and a rotation value. For instance: + +Each `tile_entry` JSON is a dictionary that describes how to map one or more game entities to one or +more sprites. The simplest version has a single game entity, a single foreground sprite, an +_optional_ background sprite, and a rotation value. For instance: + ```C++ { // this is an object and doesn't require a list "id": "mon_cat", // the game entity represented by this sprite @@ -43,33 +82,56 @@ Each `tile_entry` JSON is a dictionary that describes how to map one or more gam } ``` -The values in `"id"`, `"fg"`, and `"bg"` can be repeated within an image directory or in different image directories. `"fg"` and `"bg"` sprite images can be referenced across image directories, but the sprites must be stored in an image directory with other sprites of the same height and width. +The values in `"id"`, `"fg"`, and `"bg"` can be repeated within an image directory or in different +image directories. `"fg"` and `"bg"` sprite images can be referenced across image directories, but +the sprites must be stored in an image directory with other sprites of the same height and width. + +`"id"` can also be a list of multiple game entities sharing the same sprite, like +`"id": ["vp_door"], ["vp_hddoor"]`. `"id"` can be any vehicle part, terrain, furniture, item, or +monster in the game. The special ids `"player_female", "player_male", "npc_female", "npc_male"` are +used to identify the sprites for the player avatar and NPCs. The special id `"unknown"` provides a +sprite that is displayed when an entity has no other sprite. -`"id"` can also be a list of multiple game entities sharing the same sprite, like `"id": ["vp_door"], ["vp_hddoor"]`. `"id"` can be any vehicle part, terrain, furniture, item, or monster in the game. The special ids `"player_female", "player_male", "npc_female", "npc_male"` are used to identify the sprites for the player avatar and NPCs. The special id `"unknown"` provides a sprite that is displayed when an entity has no other sprite. +The special suffixes `_season_spring`, `_season_summer`, `_season_autumn`, and `_season_winter` can +be applied to any entity id to create a seasonal variant for that entity that will be displayed in +the appropriate season like this `"id": "mon_wolf_season_winter"`. -The special suffixes `_season_spring`, `_season_summer`, `_season_autumn`, and `_season_winter` can be applied to any entity id to create a seasonal variant for that entity that will be displayed in the appropriate season like this `"id": "mon_wolf_season_winter"`. +The special prefixes `overlay_mutation_`, `overlay_female_mutation_`, `overlay_male_mutation_` can +prefix any trait or bionic in the game to specify an overlay image that will be laid over the player +and NPC sprites to indicate they have that mutation or bionic. -The special prefixes `overlay_mutation_`, `overlay_female_mutation_`, `overlay_male_mutation_` can prefix any trait or bionic in the game to specify an overlay image that will be laid over the player and NPC sprites to indicate they have that mutation or bionic. +The special prefixes `overlay_worn_`, `overlay_female_worn_`, `overlay_male_worn_` can prefix any +item in the game to specify an overlay image that will be laid over the player and NPC sprites to +indicate they are wearing that item. -The special prefixes `overlay_worn_`, `overlay_female_worn_`, `overlay_male_worn_` can prefix any item in the game to specify an overlay image that will be laid over the player and NPC sprites to indicate they are wearing that item. +The special prefixes `overlay_wielded_`, `overlay_female_wielded_`, `overlay_male_wielded_` can +prefix any item in the game to specify an overlay image that will be laid over the player and NPC +sprites to indicate they are holding that item. -The special prefixes `overlay_wielded_`, `overlay_female_wielded_`, `overlay_male_wielded_` can prefix any item in the game to specify an overlay image that will be laid over the player and NPC sprites to indicate they are holding that item. +`"fg"` and `"bg"` can also be a list of 2 or 4 pre-rotated rotational variants, like +`"bg": ["t_wall_n", "t_wall_e", "t_wall_s", "t_wall_w"]` or +`"fg": ["mon_dog_left", "mon_dog_right"]`. -`"fg"` and `"bg"` can also be a list of 2 or 4 pre-rotated rotational variants, like `"bg": ["t_wall_n", "t_wall_e", "t_wall_s", "t_wall_w"]` or `"fg": ["mon_dog_left", "mon_dog_right"]`. +`"fg"` and `"bg"` can also be a list of dictionaries of weighted, randomly chosen options, any of +which can also be a rotated list: -`"fg"` and `"bg"` can also be a list of dictionaries of weighted, randomly chosen options, any of which can also be a rotated list: ```C++ - "fg": [ - { "weight": 50, "sprite": "t_dirt_brown"}, // appears in 50 of 53 tiles - { "weight": 1, "sprite": "t_dirt_black_specks"}, // appears 1 in 53 tiles - { "weight": 1, "sprite": "t_dirt_specks_gray"}, - { "weight": 1, "sprite": "t_patchy_grass"} // file names are arbitrary - ], +"fg": [ + { "weight": 50, "sprite": "t_dirt_brown"}, // appears in 50 of 53 tiles + { "weight": 1, "sprite": "t_dirt_black_specks"}, // appears 1 in 53 tiles + { "weight": 1, "sprite": "t_dirt_specks_gray"}, + { "weight": 1, "sprite": "t_patchy_grass"} // file names are arbitrary +], ``` -`"multitle"` is an *optional* field. If it is present and `true`, there must be an `additional_tiles` list with 1 or more dictionaries for entities and sprites associated with this tile, such as broken versions of an item or wall connections. Each dictionary in the list has an `"id`" field, as above, and a `"fg"` field, which can be a single filename, a list of filenames, or a list of dictionaries as above. +`"multitle"` is an _optional_ field. If it is present and `true`, there must be an +`additional_tiles` list with 1 or more dictionaries for entities and sprites associated with this +tile, such as broken versions of an item or wall connections. Each dictionary in the list has an +`"id`" field, as above, and a `"fg"` field, which can be a single filename, a list of filenames, or +a list of dictionaries as above. Each `tile_entry.json` file can have a single object in it, or a list of 1 or more objects like so: + ```C++ [ { "id": "mon_zombie", "fg": "mon_zombie", "bg": "mon_zombie_bg", "rotates": false }, @@ -78,20 +140,33 @@ Each `tile_entry.json` file can have a single object in it, or a list of 1 or mo ] ``` -Having a list of tile entries in a file may be useful for organization, but completely unrelated entries may all exist in the same file without any complications. +Having a list of tile entries in a file may be useful for organization, but completely unrelated +entries may all exist in the same file without any complications. #### expansion `tile_entry` JSON -Tilesheets can have expansion tilesheets, which are tilesheets from mods. Each expansion tilesheet is a single `"id"` value, `"rotates": false"`, and `"fg": 0`. Expansion `tile_entry` JSON are the only `tile_entry` JSONs that use an integer value for `"fg"` and that value must be 0. Expansion `tile_entry` JSONs must be located at the top layer of each image directory. + +Tilesheets can have expansion tilesheets, which are tilesheets from mods. Each expansion tilesheet +is a single `"id"` value, `"rotates": false"`, and `"fg": 0`. Expansion `tile_entry` JSON are the +only `tile_entry` JSONs that use an integer value for `"fg"` and that value must be 0. Expansion +`tile_entry` JSONs must be located at the top layer of each image directory. #### Sprite Images -Every sprite inside an image directory must have the same height and width as every other sprite in the image directory. -Sprites can be organized into subdirectories within the image directory however the tileset developer prefers. Sprite filenames are completely arbitrary and should be chosen using a scheme that makes sense to the tileset developer. +Every sprite inside an image directory must have the same height and width as every other sprite in +the image directory. + +Sprites can be organized into subdirectories within the image directory however the tileset +developer prefers. Sprite filenames are completely arbitrary and should be chosen using a scheme +that makes sense to the tileset developer. -After loading a tileset, config/debug.log will contain a space separated list of every entity missing a sprite in the tileset. Entities that have sprites because of a `"looks_like"` definition will not show up in the list. +After loading a tileset, config/debug.log will contain a space separated list of every entity +missing a sprite in the tileset. Entities that have sprites because of a `"looks_like"` definition +will not show up in the list. ### `tile_info.json` -Each compositing tileset *must* have a `tile_info.json`, laid out like so: + +Each compositing tileset _must_ have a `tile_info.json`, laid out like so: + ``` [ { @@ -118,125 +193,150 @@ Each compositing tileset *must* have a `tile_info.json`, laid out like so: } ] ``` -The first dictionary is mandatory, and gives the default sprite width and sprite height for all tilesheets in the tileset. Each of the image directories must have a separate dictionary, containing the tilesheet png name as its key. If the tilesheet has the default sprite dimensions and no special offsets, it can have an empty dictionary as the value for the tilesheet name key. Otherwise, it should have a dictionary of the sprite offsets, height, and width. - -A special key is `"fallback"` which should be `true` if present. If a tilesheet is designated as fallback, it will be treated as a tilesheet of fallback ASCII characters. `compose.py` will also compose the fallback tilesheet to the end of the tileset, and will add a "fallback.png" to `tile_config.json` if there is no `"fallback"` entry in `tile_info.json`. -A special is `"filler"` which should be `true` if present. If a tilesheet is designated as filler, entries from its directory will be ignored if an entry from a non-filler directory has already defined the same id. Entries will also be ignored if the id was already defined by in the filler directory. Also, pngs from a filler directory will be ignored if they share a name with a png from a non-filler directory. A filler tilesheet is useful when upgrading the art in a tileset: old, low-quality art can be placed on filler tilesheet and will be automatically replaced as better images are added to the non-filler tilesheets. +The first dictionary is mandatory, and gives the default sprite width and sprite height for all +tilesheets in the tileset. Each of the image directories must have a separate dictionary, containing +the tilesheet png name as its key. If the tilesheet has the default sprite dimensions and no special +offsets, it can have an empty dictionary as the value for the tilesheet name key. Otherwise, it +should have a dictionary of the sprite offsets, height, and width. + +A special key is `"fallback"` which should be `true` if present. If a tilesheet is designated as +fallback, it will be treated as a tilesheet of fallback ASCII characters. `compose.py` will also +compose the fallback tilesheet to the end of the tileset, and will add a "fallback.png" to +`tile_config.json` if there is no `"fallback"` entry in `tile_info.json`. + +A special is `"filler"` which should be `true` if present. If a tilesheet is designated as filler, +entries from its directory will be ignored if an entry from a non-filler directory has already +defined the same id. Entries will also be ignored if the id was already defined by in the filler +directory. Also, pngs from a filler directory will be ignored if they share a name with a png from a +non-filler directory. A filler tilesheet is useful when upgrading the art in a tileset: old, +low-quality art can be placed on filler tilesheet and will be automatically replaced as better +images are added to the non-filler tilesheets. ## Legacy tilesets + ### tilesheets -Each tilesheet contains 1 or more sprites with the same width and height. Each tilesheet contains one or more rows of exactly 16 sprites. Sprite index 0 is special and the first sprite of the first tilesheet in a tileset should be blank. Indices run sequentially through each sheet and continue incrementing for each new sheet without reseting, so index 32 is the first sprite in the third row of the first sheet. If the first sheet has 320 sprites in it, index 352 would be the first sprite of the third row of the second sheet. + +Each tilesheet contains 1 or more sprites with the same width and height. Each tilesheet contains +one or more rows of exactly 16 sprites. Sprite index 0 is special and the first sprite of the first +tilesheet in a tileset should be blank. Indices run sequentially through each sheet and continue +incrementing for each new sheet without reseting, so index 32 is the first sprite in the third row +of the first sheet. If the first sheet has 320 sprites in it, index 352 would be the first sprite of +the third row of the second sheet. ### `tile_config` -Each legacy tileset has a `tile_config.json` describing how to map the contents of a sprite sheet to various tile identifiers, different orientations, etc. The ordering of the overlays used for displaying mutations can be controlled as well. The ordering can be used to override the default ordering provided in `mutation_ordering.json`. Example: + +Each legacy tileset has a `tile_config.json` describing how to map the contents of a sprite sheet to +various tile identifiers, different orientations, etc. The ordering of the overlays used for +displaying mutations can be controlled as well. The ordering can be used to override the default +ordering provided in `mutation_ordering.json`. Example: ```C++ - { // whole file is a single object - "tile_info": [ // tile_info is mandatory - { - "height": 32, - "width": 32, - "iso" : true, // Optional. Indicates an isometric tileset. Defaults to false. - "pixelscale" : 2 // Optional. Sets a multiplier for resizing a tileset. Defaults to 1. - } - ], - "tiles-new": [ // tiles-new is an array of sprite sheets - { // alternately, just one "tiles" array - "file": "tiles.png", // file containing sprites in a grid - "tiles": [ // array with one entry per tile - { - "id": "10mm", // id is how the game maps things to sprites - "fg": 1, // lack of prefix mostly indicates items - "bg": 632, // fg and bg can be sprite indexes in the image - "rotates": false - }, - { - "id": "t_wall", // "t_" indicates terrain - "fg": [2918, 2919, 2918, 2919], // 2 or 4 sprite numbers indicates pre-rotated - "bg": 633, - "rotates": true, - "multitile": true, - "additional_tiles": [ // connected/combined versions of sprite - { // or variations, see below - "id": "center", - "fg": [2919, 2918, 2919, 2918] - }, - { - "id": "corner", - "fg": [2924, 2922, 2922, 2923] - }, - { - "id": "end_piece", - "fg": [2918, 2919, 2918, 2919] - }, - { - "id": "t_connection", - "fg": [2919, 2918, 2919, 2918] - }, - { - "id": "unconnected", - "fg": 2235 - } - ] - }, - { - "id": "vp_atomic_lamp", // "vp_" vehicle part - "fg": 3019, - "bg": 632, - "rotates": false, - "multitile": true, - "additional_tiles": [ - { - "id": "broken", // variant sprite - "fg": 3021 - } - ] - }, - { - "id": "t_dirt", - "rotates": false, - "fg": [ - { "weight":50, "sprite":640}, // weighted random variants - { "weight":1, "sprite":3620}, - { "weight":1, "sprite":3621}, - { "weight":1, "sprite":3622} - ] - }, - { - "id": [ - "overlay_mutation_GOURMAND", // character overlay for mutation - "overlay_mutation_male_GOURMAND", // overlay for specified gender - "overlay_mutation_active_GOURMAND" // overlay for activated mutation - ], - "fg": 4040 - } - ] - }, - { // second entry in tiles-new - "file": "moretiles.png", // another sprite sheet - "tiles": [ - { - "id": ["xxx","yyy"], // define two ids at once - "fg": 1, - "bg": 234 - } - ] - }d - ], - "overlay_ordering": [ - { - "id" : "WINGS_BAT", // mutation name, in a string or array of strings - "order" : 1000 // range from 0 - 9999, 9999 being the topmost layer - }, - { - "id" : [ "PLANTSKIN", "BARK" ], // mutation name, in a string or array of strings - "order" : 3500 // order is applied to all items in the array - }, - { - "id" : "bio_armor_torso", // Overlay order of bionics is controlled in the same way - "order" : 500 - } - ] - } +{ // whole file is a single object + "tile_info": [ // tile_info is mandatory + { + "height": 32, + "width": 32, + "iso" : true, // Optional. Indicates an isometric tileset. Defaults to false. + "pixelscale" : 2 // Optional. Sets a multiplier for resizing a tileset. Defaults to 1. + } + ], + "tiles-new": [ // tiles-new is an array of sprite sheets + { // alternately, just one "tiles" array + "file": "tiles.png", // file containing sprites in a grid + "tiles": [ // array with one entry per tile + { + "id": "10mm", // id is how the game maps things to sprites + "fg": 1, // lack of prefix mostly indicates items + "bg": 632, // fg and bg can be sprite indexes in the image + "rotates": false + }, + { + "id": "t_wall", // "t_" indicates terrain + "fg": [2918, 2919, 2918, 2919], // 2 or 4 sprite numbers indicates pre-rotated + "bg": 633, + "rotates": true, + "multitile": true, + "additional_tiles": [ // connected/combined versions of sprite + { // or variations, see below + "id": "center", + "fg": [2919, 2918, 2919, 2918] + }, + { + "id": "corner", + "fg": [2924, 2922, 2922, 2923] + }, + { + "id": "end_piece", + "fg": [2918, 2919, 2918, 2919] + }, + { + "id": "t_connection", + "fg": [2919, 2918, 2919, 2918] + }, + { + "id": "unconnected", + "fg": 2235 + } + ] + }, + { + "id": "vp_atomic_lamp", // "vp_" vehicle part + "fg": 3019, + "bg": 632, + "rotates": false, + "multitile": true, + "additional_tiles": [ + { + "id": "broken", // variant sprite + "fg": 3021 + } + ] + }, + { + "id": "t_dirt", + "rotates": false, + "fg": [ + { "weight":50, "sprite":640}, // weighted random variants + { "weight":1, "sprite":3620}, + { "weight":1, "sprite":3621}, + { "weight":1, "sprite":3622} + ] + }, + { + "id": [ + "overlay_mutation_GOURMAND", // character overlay for mutation + "overlay_mutation_male_GOURMAND", // overlay for specified gender + "overlay_mutation_active_GOURMAND" // overlay for activated mutation + ], + "fg": 4040 + } + ] + }, + { // second entry in tiles-new + "file": "moretiles.png", // another sprite sheet + "tiles": [ + { + "id": ["xxx","yyy"], // define two ids at once + "fg": 1, + "bg": 234 + } + ] + }d + ], + "overlay_ordering": [ + { + "id" : "WINGS_BAT", // mutation name, in a string or array of strings + "order" : 1000 // range from 0 - 9999, 9999 being the topmost layer + }, + { + "id" : [ "PLANTSKIN", "BARK" ], // mutation name, in a string or array of strings + "order" : 3500 // order is applied to all items in the array + }, + { + "id" : "bio_armor_torso", // Overlay order of bionics is controlled in the same way + "order" : 500 + } + ] +} ``` diff --git a/doc/TRANSLATING.md b/doc/TRANSLATING.md index f1e53d090c1a..9e704a7047c3 100644 --- a/doc/TRANSLATING.md +++ b/doc/TRANSLATING.md @@ -1,88 +1,88 @@ # Translating Cataclysm: BN -* [Translators](#translators) - * [Getting Started](#getting-Started) - * [Grammatical gender](#grammatical-gender) - * [Tips](#tips) -* [Developers](#developers) - * [Translation Functions](#translation-functions) - * [`translation`](#translation) - * [Recommendations](#recommendations) -* [Maintainers](#maintainers) +- [Translating Cataclysm: BN](#translating-cataclysm-bn) + - [Translators](#translators) + - [Getting Started](#getting-started) + - [Grammatical gender](#grammatical-gender) + - [Tips](#tips) + - [Developers](#developers) + - [Translation Functions](#translation-functions) + - [`_()`](#_) + - [`pgettext()`](#pgettext) + - [`vgettext()`](#vgettext) + - [`vpgettext()`](#vpgettext) + - [`translation`](#translation) + - [Lua](#lua) + - [Recommendations](#recommendations) + - [Maintainers](#maintainers) ## Translators -The official location for translating Cataclysm: BN is the -[Transifex translations project][1]. +The official location for translating Cataclysm: BN is the [Transifex translations project][1]. -If you're looking for a way to translate mods not included -in game repository, see [TRANSLATING_MODS.md](TRANSLATING_MODS.md). +If you're looking for a way to translate mods not included in game repository, see +[TRANSLATING_MODS.md](TRANSLATING_MODS.md). Some of the currently supported languages are: -* Arabic -* Bulgarian -* Chinese (Simplified) -* Chinese (Traditional) -* Dutch -* Esperanto -* French -* German -* Italian (Italy) -* Japanese -* Korean -* Polish -* Portuguese (Brazil) -* Russian -* Serbian -* Spanish (Argentina) -* Spanish (Spain) -* Turkish - -Don't see your language in the list above? You can add it into the project at -Transifex! +- Arabic +- Bulgarian +- Chinese (Simplified) +- Chinese (Traditional) +- Dutch +- Esperanto +- French +- German +- Italian (Italy) +- Japanese +- Korean +- Polish +- Portuguese (Brazil) +- Russian +- Serbian +- Spanish (Argentina) +- Spanish (Spain) +- Turkish + +Don't see your language in the list above? You can add it into the project at Transifex! ### Getting Started -To begin translating, head over the [translation project][1] and click on the -"Help Translate Cataclysm: BN" button. -This should take you to a page where you can either create a free account on +To begin translating, head over the [translation project][1] and click on the "Help Translate +Cataclysm: BN" button. This should take you to a page where you can either create a free account on Transifex, or login using GitHub, Google+ or LinkedIn. ![Start translating](img/translating-start.png) -After you've created your account, return to the [translation project][1] and -click on the "Join team" button. -This will open a window where you can choose the language you are interested on +After you've created your account, return to the [translation project][1] and click on the "Join +team" button. This will open a window where you can choose the language you are interested on translating, so pick one and click the "Join" button. ![Join project](img/translating-join.png) -After this, the most straightforward thing to do is to reload the page, -which should redirect you to the translation project's dashboard. -Here, you can click the "Languages" link on the sidebar to see the list of -supported languages and the current progress of the translation effort. +After this, the most straightforward thing to do is to reload the page, which should redirect you to +the translation project's dashboard. Here, you can click the "Languages" link on the sidebar to see +the list of supported languages and the current progress of the translation effort. -Note that you can request for the inclusion of additional languages, -if the one you are interested in is not available on the list. +Note that you can request for the inclusion of additional languages, if the one you are interested +in is not available on the list. ![Language list](img/translating-list.png) -From this list, you can click on the language of your choice, and then click on -the "Translate" to get started right away. Otherwise, you can click on any -other language and click on the "Join team" button, if you are interested in -translating for that language as well. +From this list, you can click on the language of your choice, and then click on the "Translate" to +get started right away. Otherwise, you can click on any other language and click on the "Join team" +button, if you are interested in translating for that language as well. -After clicking on the "Translate" button, you will be taken to the web editor. -To begin, you need to choose a resource to translate. Most of the in-game text -is contained in the `cataclysm-bright-nights` resource, so click on it to start. +After clicking on the "Translate" button, you will be taken to the web editor. To begin, you need to +choose a resource to translate. Most of the in-game text is contained in the +`cataclysm-bright-nights` resource, so click on it to start. ![Choose a resource](img/translating-resource.png) -At this point, the editor should show you the list of text available for -translation, now you only need to click on the string you want to translate and -type your translation on the translation area on the right side of the screen. -Click on the "Save" button when you are satisfied with your translation. +At this point, the editor should show you the list of text available for translation, now you only +need to click on the string you want to translate and type your translation on the translation area +on the right side of the screen. Click on the "Save" button when you are satisfied with your +translation. ![Web editor](img/translating-editor.png) @@ -90,75 +90,68 @@ See [Transifex's documentation][2] for more information. ### Grammatical gender -For NPC dialogue (and potentially other strings) some languages may wish to -have alternate translations depending on the gender of the conversation -participants. This two pieces of initial configuration. +For NPC dialogue (and potentially other strings) some languages may wish to have alternate +translations depending on the gender of the conversation participants. This two pieces of initial +configuration. -1. The dialogue must have the relevant genders listed in the json file defining - it. See [the NPC docs](NPCs.md). -2. Each language must specify the genders it wishes to use via `genders` list - of the language's entry in `data/raw/languages.json`. Don't add genders there - until you're sure you will need them, because it will make more work for - you. Current choices are: `m` (male), `f` (female), `n` (neuter). - If you need different genders than the ones currently supported, see - relevant note in `src/language.h`. +1. The dialogue must have the relevant genders listed in the json file defining it. See + [the NPC docs](NPCs.md). +2. Each language must specify the genders it wishes to use via `genders` list of the language's + entry in `data/raw/languages.json`. Don't add genders there until you're sure you will need them, + because it will make more work for you. Current choices are: `m` (male), `f` (female), `n` + (neuter). If you need different genders than the ones currently supported, see relevant note in + `src/language.h`. -Having done this, the relevant dialogue lines will appear multiple times for -translation, with different genders specified in the message context. For -example, a context of `npc:m` would indicate that the NPC participant in the -conversation is male. +Having done this, the relevant dialogue lines will appear multiple times for translation, with +different genders specified in the message context. For example, a context of `npc:m` would indicate +that the NPC participant in the conversation is male. -Because of technical limitations, all supported genders will appear as -contexts, but you only need to provide translations for the genders listed in -the grammatical gender list for your language. +Because of technical limitations, all supported genders will appear as contexts, but you only need +to provide translations for the genders listed in the grammatical gender list for your language. -Other parts of the game have various ad hoc solutions to grammatical gender, so -don't be surprised to see other contexts appearing for other strings. +Other parts of the game have various ad hoc solutions to grammatical gender, so don't be surprised +to see other contexts appearing for other strings. ### Tips -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. 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. -Information about these and any other issues specific to individual languages, -can be found in Cataclysm: BN's [language notes folder][3]. +Information about these and any other issues specific to individual languages, can be found in +Cataclysm: BN's [language notes folder][3]. -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. +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. -Cataclysm: BN has more than 14000 translatable strings, but don't be discouraged. -The more translators there are, the easier it becomes 😄. +Cataclysm: BN has more than 14000 translatable strings, but don't be discouraged. The more +translators there are, the easier it becomes 😄. ## Developers -Cataclysm: BN uses custom runtime library that works similarly to -[GNU gettext][4] to display translated texts. +Cataclysm: BN uses custom runtime library that works similarly to [GNU gettext][4] to display +translated texts. Using `gettext` requires two actions: -* Marking strings that should be translated in the source code. -* Calling translation functions at run time. +- Marking strings that should be translated in the source code. +- Calling translation functions at run time. -Marking translatable string allows for their automatic extraction. -This process generates a file that maps the original string (usually in English) -as it appears in the source code to the translated string. -These mappings are used at run time by the translation functions. +Marking translatable string allows for their automatic extraction. This process generates a file +that maps the original string (usually in English) as it appears in the source code to the +translated string. These mappings are used at run time by the translation functions. -Note that only extracted strings can get translated, since the original string -is acting as the identifier used to request the translation. -If a translation function can't find the translation, it returns the original -string. +Note that only extracted strings can get translated, since the original string is acting as the +identifier used to request the translation. If a translation function can't find the translation, it +returns the original string. ### Translation Functions -In order to mark a string for translation and to obtain its translation at -runtime, you should use one of the following functions and classes. +In order to mark a string for translation and to obtain its translation at runtime, you should use +one of the following functions and classes. -String *literals* that are used in any of these functions are automatically -extracted. Non-literal strings are still translated at run time, but they won't -get extracted. +String _literals_ that are used in any of these functions are automatically extracted. Non-literal +strings are still translated at run time, but they won't get extracted. #### `_()` @@ -174,21 +167,18 @@ It also works directly: add_msg( _( "You drop the %s." ), the_item_name ); ``` -Strings from the JSON files are extracted by the `lang/extract_json_strings.py` -script, and can be translated at run time using `_()`. If translation context -is desired for a JSON string, `class translation` can be used instead, which is -documented below. +Strings from the JSON files are extracted by the `lang/extract_json_strings.py` script, and can be +translated at run time using `_()`. If translation context is desired for a JSON string, +`class translation` can be used instead, which is documented below. #### `pgettext()` -This function is useful when the original string's meaning is ambiguous in -isolation. For example, the word "blue", which can mean either a color or an -emotion. +This function is useful when the original string's meaning is ambiguous in isolation. For example, +the word "blue", which can mean either a color or an emotion. -In addition to the translatable string, `pgettext` receives a context which is -provided to the translators, but is not part of the translated string itself. -This function's first parameter is the context, the second is the string to be -translated: +In addition to the translatable string, `pgettext` receives a context which is provided to the +translators, but is not part of the translated string itself. This function's first parameter is the +context, the second is the string to be translated: ```c++ const char *translated = pgettext( "The color", "blue" ); @@ -196,11 +186,10 @@ const char *translated = pgettext( "The color", "blue" ); #### `vgettext()` -Some languages have complex rules for plural forms. `vgettext` can be used to -translate these plurals correctly. Its first parameter is the untranslated -string in singular form, the second parameter is the untranslated string in -plural form and the third one is used to determine which one of the first two -should be used at run time: +Some languages have complex rules for plural forms. `vgettext` can be used to translate these +plurals correctly. Its first parameter is the untranslated string in singular form, the second +parameter is the untranslated string in plural form and the third one is used to determine which one +of the first two should be used at run time: ```c++ const char *translated = vgettext( "%d zombie", "%d zombies", num_of_zombies ); @@ -216,10 +205,9 @@ const char *translated = vpgettext( "water source, not time of year", "%d spring ### `translation` -There are times when you want to store a string for translation, maybe with -translation context; Sometimes you may also want to store a string that needs no -translation or has plural forms. `class translation` in `translations.h|cpp` -offers these functionalities in a single wrapper: +There are times when you want to store a string for translation, maybe with translation context; +Sometimes you may also want to store a string that needs no translation or has plural forms. +`class translation` in `translations.h|cpp` offers these functionalities in a single wrapper: ```c++ const translation text = to_translation( "Context", "Text" ); @@ -252,9 +240,9 @@ const std::string translated = text.translated(); const std::string translated = text.translated( 2 ); ``` -`class translation` can also be read from JSON. The method `translation::deserialize()` -handles deserialization from a `JsonIn` object, so translations can be read from -JSON using the appropriate JSON functions. The JSON syntax is as follows: +`class translation` can also be read from JSON. The method `translation::deserialize()` handles +deserialization from a `JsonIn` object, so translations can be read from JSON using the appropriate +JSON functions. The JSON syntax is as follows: ```JSON "name": "bar" @@ -270,22 +258,20 @@ or "name": { "ctxt": "foo", "str_sp": "foo" } ``` -In the above code, `"ctxt"` and `"str_pl"` are both optional, whereas `"str_sp"` -is equivalent to specifying `"str"` and `"str_pl"` with the same string. Additionally, -`"str_pl"` and `"str_sp"` will only be read if the translation object is constructed using -`plural_tag` or `pl_translation()`, or converted using `make_plural()`. Here's -an example: +In the above code, `"ctxt"` and `"str_pl"` are both optional, whereas `"str_sp"` is equivalent to +specifying `"str"` and `"str_pl"` with the same string. Additionally, `"str_pl"` and `"str_sp"` will +only be read if the translation object is constructed using `plural_tag` or `pl_translation()`, or +converted using `make_plural()`. Here's an example: ```c++ translation name{ translation::plural_tag() }; jsobj.read( "name", name ); ``` -If neither "str_pl" nor "str_sp" is specified, the plural form defaults to the -singular form + "s". +If neither "str_pl" nor "str_sp" is specified, the plural form defaults to the singular form + "s". -You can also add comments for translators by writing it like below (the order -of the entries does not matter): +You can also add comments for translators by writing it like below (the order of the entries does +not matter): ```JSON "name": { @@ -294,102 +280,112 @@ of the entries does not matter): } ``` -Do note that currently the JSON syntax is only supported for some JSON values, -which are listed below. If you want other json strings to use this format, -refer to `translations.h|cpp` and migrate the corresponding code. Afterwards -you may also want to test `update_pot.sh` to ensure that the strings are -correctly extracted for translation, and run the unit test to fix text styling -issues reported by the `translation` class. - -| Supported JSON values -|--- -| Effect names -| Item action names -| Item category names -| Activity verbs -| Gate action messages -| Spell names and descriptions -| Terrain/furniture descriptions -| Monster melee attack messages -| Morale effect descriptions -| Mutation names/descriptions -| NPC class names/descriptions -| Tool quality names -| Score descriptions -| Skill names/descriptions -| Bionic names/descriptions -| Terrain bash sound descriptions -| Trap-vehicle collision sound descriptions -| Vehicle part names/descriptions -| Skill display type names -| NPC dialogue u_buy_monster unique names -| Spell messages and monster spell messages -| Martial art names and descriptions -| Mission names and descriptions -| Fault names and descriptions -| Plant names in item seed data -| Transform use action messages and menu text -| Template NPC names and name suffixes -| NPC talk response text -| Relic name overrides -| Relic recharge messages -| Speech text -| Tutorial messages -| Vitamin names -| Recipe blueprint names -| Recipe group recipe descriptions -| Item names (plural supported) and descriptions -| Recipe descriptions -| Inscribe use action verbs/gerunds -| Monster names (plural supported) and descriptions -| Snippets -| Bodypart names -| Keybinding action names -| Field level names +Do note that currently the JSON syntax is only supported for some JSON values, which are listed +below. If you want other json strings to use this format, refer to `translations.h|cpp` and migrate +the corresponding code. Afterwards you may also want to test `update_pot.sh` to ensure that the +strings are correctly extracted for translation, and run the unit test to fix text styling issues +reported by the `translation` class. + +| Supported JSON values | +| ------------------------------------------------- | +| Effect names | +| Item action names | +| Item category names | +| Activity verbs | +| Gate action messages | +| Spell names and descriptions | +| Terrain/furniture descriptions | +| Monster melee attack messages | +| Morale effect descriptions | +| Mutation names/descriptions | +| NPC class names/descriptions | +| Tool quality names | +| Score descriptions | +| Skill names/descriptions | +| Bionic names/descriptions | +| Terrain bash sound descriptions | +| Trap-vehicle collision sound descriptions | +| Vehicle part names/descriptions | +| Skill display type names | +| NPC dialogue u_buy_monster unique names | +| Spell messages and monster spell messages | +| Martial art names and descriptions | +| Mission names and descriptions | +| Fault names and descriptions | +| Plant names in item seed data | +| Transform use action messages and menu text | +| Template NPC names and name suffixes | +| NPC talk response text | +| Relic name overrides | +| Relic recharge messages | +| Speech text | +| Tutorial messages | +| Vitamin names | +| Recipe blueprint names | +| Recipe group recipe descriptions | +| Item names (plural supported) and descriptions | +| Recipe descriptions | +| Inscribe use action verbs/gerunds | +| Monster names (plural supported) and descriptions | +| Snippets | +| Bodypart names | +| Keybinding action names | +| Field level names | + +### Lua + +The 4 translation functions are exposed to the Lua code. See [LUA_SUPPORT.md](LUA_SUPPORT.md) for +details. ### Recommendations -In Cataclysm: BN, some classes, like `itype` and `mtype`, provide a wrapper -for the translation functions, called `nname`. +In Cataclysm: BN, some classes, like `itype` and `mtype`, provide a wrapper for the translation +functions, called `nname`. -When an empty string is marked for translation, it is always translated into -debug information, rather than an empty string. -On most cases, strings can be considered to be never empty, and thus always -safe to mark for translation, however, when handling a string that can be empty -and *needs* to remain empty after translation, the string should be checked for -emptiness and only passed to a translation function when is non-empty. +When an empty string is marked for translation, it is always translated into debug information, +rather than an empty string. On most cases, strings can be considered to be never empty, and thus +always safe to mark for translation, however, when handling a string that can be empty and _needs_ +to remain empty after translation, the string should be checked for emptiness and only passed to a +translation function when is non-empty. -Error and debug messages must not be marked for translation. -When they appear, the player is expected to report them *exactly* as they are -printed by the game. +Error and debug messages must not be marked for translation. When they appear, the player is +expected to report them _exactly_ as they are printed by the game. See the [gettext manual][5] for more information. ## Maintainers -Several steps need to be done in the correct order to correctly merge and maintain the translation files. +Several steps need to be done in the correct order to correctly merge and maintain the translation +files. There are scripts available for these, so usually the process will be as follows: 1. Download the translations in `.po` format. 2. Put them in `lang/incoming/`, ensuring they are named consistently with the files in `lang/po/`. -3. Run `lang/update_pot.sh` to update `lang/po/cataclysm-BN.pot` (requires python with `polib` library installed). -4. Run `lang/merge_po.sh` to update `lang/po/*.po`. (This is only used to test translations locally as the project now uses Transifex for translation) +3. Run `lang/update_pot.sh` to update `lang/po/cataclysm-BN.pot` (requires python with `polib` and + `luaparser` modules installed). +4. Run `lang/merge_po.sh` to update `lang/po/*.po`. (This is only used to test translations locally + as the project now uses Transifex for translation) - This will also merge the translations from `lang/incoming/`. + This will also merge the translations from `lang/incoming/`. These steps should be enough to keep the translation files up-to-date. -To compile the .po files into `.mo` files for use, run `lang/compile_mo.sh`. It will create a directory in `lang/mo/` for each language found. +To compile the .po files into `.mo` files for use, run `lang/compile_mo.sh`. It will create a +directory in `lang/mo/` for each language found. -Also note that both `lang/merge_po.sh` and `lang/compile_mo.sh` accept arguments specifying which languages to merge or compile. So to compile only the translation for, say, Traditional Chinese (zh_TW), one would run `lang/compile_mo.sh zh_TW`. +Also note that both `lang/merge_po.sh` and `lang/compile_mo.sh` accept arguments specifying which +languages to merge or compile. So to compile only the translation for, say, Traditional Chinese +(zh_TW), one would run `lang/compile_mo.sh zh_TW`. -After compiling the appropriate .mo file, if the language has been selected in game settings, the translations will be automatically used when you run cataclysm. +After compiling the appropriate .mo file, if the language has been selected in game settings, the +translations will be automatically used when you run cataclysm. -When `System language` is selected in settings, the game tries to use language that matches system language based on language definitions file `data/raw/languages.json`. - -If you're testing translations for a new language, or the language does not show up in settings, make sure it has its own entry in the definitions file. +When `System language` is selected in settings, the game tries to use language that matches system +language based on language definitions file `data/raw/languages.json`. +If you're testing translations for a new language, or the language does not show up in settings, +make sure it has its own entry in the definitions file. [1]: https://app.transifex.com/bn-team/cataclysm-bright-nights [2]: https://docs.transifex.com/ diff --git a/doc/TRANSLATING_MODS.md b/doc/TRANSLATING_MODS.md index 1c037f911bde..d4d12fb42649 100644 --- a/doc/TRANSLATING_MODS.md +++ b/doc/TRANSLATING_MODS.md @@ -1,65 +1,87 @@ # Translating mods for Cataclysm: BN -- [Intro](#intro) -- [A short glossary](#a-short-glossary) -- [Workflow overview](#workflow-overview) -- [Setting up environment for string extraction](#setting-up-environment-for-string-extraction) -- [Extracting strings](#extracting-strings) -- [Creating new PO](#creating-new-po) -- [Updating existing PO](#updating-existing-po) -- [Compiling PO into MO](#compiling-po-into-mo) -- [Adding MO file to the mod](#adding-mo-file-to-the-mod) -- [Miscellaneous notes](#miscellaneous-notes) +- [Translating mods for Cataclysm: BN](#translating-mods-for-cataclysm-bn) + - [Intro](#intro) + - [A short glossary](#a-short-glossary) + - [POT file](#pot-file) + - [PO file](#po-file) + - [MO file](#mo-file) + - [Workflow overview](#workflow-overview) + - [Setting up environment for string extraction](#setting-up-environment-for-string-extraction) + - [Extracting strings](#extracting-strings) + - [Creating new PO](#creating-new-po) + - [Poedit](#poedit) + - [msginit](#msginit) + - [Updating existing PO](#updating-existing-po) + - [Poedit](#poedit-1) + - [msgmerge](#msgmerge) + - [Compiling PO into MO](#compiling-po-into-mo) + - [Poedit](#poedit-2) + - [msgfmt](#msgfmt) + - [Adding MO file to the mod](#adding-mo-file-to-the-mod) + - [Miscellaneous notes](#miscellaneous-notes) + - [Is it possible to use arbitrary location or names for MO files, like with JSONs?](#is-it-possible-to-use-arbitrary-location-or-names-for-mo-files-like-with-jsons) + - [Reloading translations in a running game](#reloading-translations-in-a-running-game) + - [MO load order](#mo-load-order) + - [Dialects](#dialects) + - [What if 2 or more mods provide different translations for same string?](#what-if-2-or-more-mods-provide-different-translations-for-same-string) ## Intro -This document aims to give a brief explanation on how to set up and operate -mod translation workflow for Cataclysm: Bright Nights. + +This document aims to give a brief explanation on how to set up and operate mod translation workflow +for Cataclysm: Bright Nights. For mod localization the game uses custom localization system that is similar to [GNU gettext](https://www.gnu.org/software/gettext/) and is compatible with GNU gettext MO files. -While it's possible to use Transifex or any other platform or software that supports gettext, -this document only gives examples on how to work with [Poedit](https://poedit.net/) and -command-line [GNU gettext utilities](https://www.gnu.org/software/gettext/). +While it's possible to use Transifex or any other platform or software that supports gettext, this +document only gives examples on how to work with [Poedit](https://poedit.net/) and command-line +[GNU gettext utilities](https://www.gnu.org/software/gettext/). -If you desire an in-depth explanation on PO/POT/MO files or how to work with them using GNU gettext utilities, -see [GNU gettext manual](https://www.gnu.org/software/gettext/manual/gettext.html). +If you desire an in-depth explanation on PO/POT/MO files or how to work with them using GNU gettext +utilities, see [GNU gettext manual](https://www.gnu.org/software/gettext/manual/gettext.html). -To get some generic tips on translating strings for Cataclysm: Bright Nights and its mods, -see [TRANSLATING.md](TRANSLATING.md). +To get some generic tips on translating strings for Cataclysm: Bright Nights and its mods, see +[TRANSLATING.md](TRANSLATING.md). ## A short glossary + ### POT file + Portable Object Template file (`.pot`). -This is a text file that contains original (English) strings extracted from mod's JSON files. -The POT file is a template used for creating empty or updating existing PO files of any language. +This is a text file that contains original (English) strings extracted from mod's JSON and Lua +source files. The POT file is a template used for creating empty or updating existing PO files of +any language. ### PO file + Portable Object file (`.po`). -This is a text file that contains translated strings for one language. -The PO files are what translators work with, and what will be compiled into a MO file. +This is a text file that contains translated strings for one language. The PO files are what +translators work with, and what will be compiled into a MO file. ### MO file + Machine Object file (`.mo`). -This is a binary file that contains translated strings for one language. -The MO files are what the game loads, and where it gets translated strings from. +This is a binary file that contains translated strings for one language. The MO files are what the +game loads, and where it gets translated strings from. ## Workflow overview + The first translation workflow is as follows: -1. Extract strings from mod JSON files into a POT file +1. Extract strings from mod JSON and Lua source files into a POT file 2. Create PO file for target language from this POT 3. Fill the PO file with translated strings 4. Compile PO into MO 5. Put the MO into your mod files -As the mod changes with time, so may change its strings. -Updating existing translations is done as follows: +As the mod changes with time, so may change its strings. Updating existing translations is done as +follows: -1. Extract strings from mod JSON files into a new POT file +1. Extract strings from mod JSON and Lua source files into a new POT file 2. Update existing PO file from the new POT file 3. Add new or edit existing translated strings in the PO file 4. Compile PO into MO @@ -67,71 +89,87 @@ Updating existing translations is done as follows: Step 1 in both workflows requires you to set up environment for string extraction (see below). -Steps 2-4 can be done using translation software either by the mod author/maintainer, or by the translator. +Steps 2-4 can be done using translation software either by the mod author/maintainer, or by the +translator. ## Setting up environment for string extraction -You'll need Python 3 with `polib` library installed (available via `pip`). + +You'll need Python 3 with `polib` and `luaparser` modules installed (available via `pip`). Scripts for string extraction can be found in the `lang` subdirectory of the repository: -* `extract_json_strings.py` - main string extraction routines -* `dedup_pot_file.py` - fixes errors in POT file produces by the 1st script -* `extract_mod_strings.bat` (`extract_mod_strings.sh` for Linux/MacOS) - to automate the other 2 scripts + +- `extract_json_strings.py` - main string extraction routines +- `dedup_pot_file.py` - fixes errors in POT file produces by the 1st script +- `extract_mod_strings.bat` (`extract_mod_strings.sh` for Linux/MacOS) - to automate the other 2 + scripts ## Extracting strings + Copy these 3 scripts into the mod's folder and: -* on Windows, double-click `extract_mod_strings.bat` -* on Linux/MacOS, open terminal and run `./extract_mod_strings.sh` -If the process completed without errors, you'll see a new `lang` folder -with `extracted_strings.pot` file inside. +- on Windows, double-click `extract_mod_strings.bat` +- on Linux/MacOS, open terminal and run `./extract_mod_strings.sh` + +If the process completed without errors, you'll see a new `lang` folder with `extracted_strings.pot` +file inside. ## Creating new PO + Before creating PO file, you need to choose language id. Open `data/raw/languages.json` to see the list of languages supported by the game. -In this list, each entry has its own id in form of `ln_LN`, -where `ln` determines language and `LN` - dialect. -You can either use full `ln_LN` for exact language+dialect match, -or `ln` if you want the game to use your MO regardless of dialect. +In this list, each entry has its own id in form of `ln_LN`, where `ln` determines language and +`LN` - dialect. You can either use full `ln_LN` for exact language+dialect match, or `ln` if you +want the game to use your MO regardless of dialect. ### Poedit + 1. Open the POT file with Poedit 2. Press "Create new translation" button (should show up near the bottom) 3. In language selection dialog, enter language id you chose 4. Save the file as `path/to/mod/lang/LANG.po` where `LANG` is the same language id ### msginit + ```bash msginit -i lang/index.pot -o lang/LANG.po -l LANG.UTF-8 --no-translator ``` + Where `LANG` is the language id you chose ## Updating existing PO + ### Poedit + 1. Open the PO file with Poedit 2. Choose `Catalog->Update from POT file...` and select the new POT file 3. Save the file ### msgmerge + ```bash msgmerge lang/LANG.po lang/index.pot ``` ## Compiling PO into MO + ### Poedit + 1. Open the PO file with Poedit -2. Make sure MO file will be encoded using UTF-8 (it should do so by default, - you can double check in `Catalog->Properties->"Translation properties" tab->Charset`). -3. By default, each time PO file is saved Poedit automatically compiles it into MO, - but the same can also be done explicitly via `File->Compile to MO...` +2. Make sure MO file will be encoded using UTF-8 (it should do so by default, you can double check + in `Catalog->Properties->"Translation properties" tab->Charset`). +3. By default, each time PO file is saved Poedit automatically compiles it into MO, but the same can + also be done explicitly via `File->Compile to MO...` ### msgfmt + ``` msgfmt -o lang/LANG.mo lang/LANG.po ``` ## Adding MO file to the mod + Create `lang` directory in the mod files directory and put MOs there: ``` @@ -144,9 +182,8 @@ mods/ zh_CN.mo ``` -**Note:** Storing your POT/PO files -in the same `lang` subdirectory may make it easier to keep track of them. -The game ignores these files, and your mod folder structure will look like this: +**Note:** Storing your POT/PO files in the same `lang` subdirectory may make it easier to keep track +of them. The game ignores these files, and your mod folder structure will look like this: ``` mods/ @@ -163,23 +200,27 @@ mods/ ``` ## Miscellaneous notes + ### Is it possible to use arbitrary location or names for MO files, like with JSONs? -No. The game looks for MO files with specific names that are located in the -`lang` subdirectory of the mod's `path` directory specified in `modinfo.json` -(if not specified, `path` matches the mod's directory). -However, any mod will automatically try to use any other mod's translation -files to translate its strings. This makes it possible to create mods that are -purely "translation packs" for other mods (or mod collections). +No. The game looks for MO files with specific names that are located in the `lang` subdirectory of +the mod's `path` directory specified in `modinfo.json` (if not specified, `path` matches the mod's +directory). + +However, any mod will automatically try to use any other mod's translation files to translate its +strings. This makes it possible to create mods that are purely "translation packs" for other mods +(or mod collections). ### Reloading translations in a running game -Open debug menu and select `Info...->Reload translations`, -and the game will reload all MO files from disk. -This makes it easy to see how translated string looks in game, -provided the translator has a way to compile MO files. +Open debug menu and select `Info...->Reload translations`, and the game will reload all MO files +from disk. + +This makes it easy to see how translated string looks in game, provided the translator has a way to +compile MO files. Example workflow with Poedit: + 1. Translate a string 2. Hit Ctrl+S 3. Alt+Tab into the game @@ -187,35 +228,40 @@ Example workflow with Poedit: 5. The game now displays translated string ### MO load order + MO load order is as follows: -1. First and always goes base game's MO file, which contains translation strings - for UI, hardcoded functionality, base "mod" (`data/json/`) and in-repo mods. + +1. First and always goes base game's MO file, which contains translation strings for UI, hardcoded + functionality, base "mod" (`data/json/`) and in-repo mods. 2. Then MO files of mods are loaded, in same order as the mod load order. ### Dialects -When loading MO files, the game first looks for the file with -exact language and dialect match in its name. -If such file is absent, then it looks for a file with no dialect. + +When loading MO files, the game first looks for the file with exact language and dialect match in +its name. If such file is absent, then it looks for a file with no dialect. For example, when using `Español (España)` the selection order is + 1. `es_ES.mo` 2. `es.mo` And when using `Español (Argentina)` the selection order is + 1. `es_AR.mo` 2. `es.mo` -Thus, `es.mo` would be loaded for either dialect of Spanish -if the exact translation files are not present. +Thus, `es.mo` would be loaded for either dialect of Spanish if the exact translation files are not +present. ### What if 2 or more mods provide different translations for same string? + Then the game selects which one to use according to this set of rules: -1. If string A's translation has plural forms, but string B's translation does not, - then translation A is used for both single and plural forms. -2. If both translation A and B have (or both don't have) plural forms, then - the first loaded translation is used (see MO load order). - -If you want a different translation from the one in the base game, -or don't want it to conflict with a string from some other mod, -add a translation context to the string in the corresponding JSON object -(see [TRANSLATING.md](TRANSLATING.md) for which fields support translation context). + +1. If string A's translation has plural forms, but string B's translation does not, then translation + A is used for both single and plural forms. +2. If both translation A and B have (or both don't have) plural forms, then the first loaded + translation is used (see MO load order). + +If you want a different translation from the one in the base game, or don't want it to conflict with +a string from some other mod, add a translation context to the string in the corresponding JSON +object (see [TRANSLATING.md](TRANSLATING.md) for which fields support translation context). diff --git a/doc/USER_INTERFACE.md b/doc/USER_INTERFACE.md index 87f0ba27bcf4..7d58e9904f57 100644 --- a/doc/USER_INTERFACE.md +++ b/doc/USER_INTERFACE.md @@ -1,12 +1,11 @@ # User Interface -Cataclysm: Bright Nights uses ncurses, or in the case of the tiles build, an -ncurses port, for user interface. Window management is achieved by `ui_adaptor`, -which requires a resizing callback and a redrawing callback for each UI to handle -resizing and redrawing. Details on how to use `ui_adaptor` can be found within -`ui_manager.h`. +Cataclysm: Bright Nights uses ncurses, or in the case of the tiles build, an ncurses port, for user +interface. Window management is achieved by `ui_adaptor`, which requires a resizing callback and a +redrawing callback for each UI to handle resizing and redrawing. Details on how to use `ui_adaptor` +can be found within `ui_manager.h`. + +Some good examples of the usage of `ui_adaptor` can be found within the following files: -Some good examples of the usage of `ui_adaptor` can be found within the following -files: - `query_popup` and `static_popup` in `popup.h/cpp` - `Messages::dialog` in `messages.cpp` diff --git a/doc/VEHICLES_JSON.md b/doc/VEHICLES_JSON.md index 962a3d2f6753..7cddfb36d046 100644 --- a/doc/VEHICLES_JSON.md +++ b/doc/VEHICLES_JSON.md @@ -1,6 +1,7 @@ # Vehicle prototypes JSON file contents -Vehicle prototypes are used to spawn stock vehicles. After a vehicle has been spawned, it is saved in a different format. +Vehicle prototypes are used to spawn stock vehicles. After a vehicle has been spawned, it is saved +in a different format. Vehicle prototypes do not currently accept copy-from @@ -35,27 +36,32 @@ Vehicle prototypes do not currently accept copy-from ] ``` -.* Important! *. Vehicle parts must be defined in the same order you would install them in the game (ie, frames and mount points first). You also cannot break the normal rules of installation (you can't stack non-stackable part flags). +.* Important! *. Vehicle parts must be defined in the same order you would install them in the game +(ie, frames and mount points first). You also cannot break the normal rules of installation (you +can't stack non-stackable part flags). ### Parts list -The part list contains an arbitary number of lines. Each line is of the form: - { "x": X, "y": Y, "part": PARTID, ... } -or - { "x": X, "y": Y, "parts": [ PARTID1, ... ] } -In the first form, the line defines a single part at location X,Y of vehicle part type PARTID. It can have the optional "ammo", "ammo_types", "ammo_qty", or "fuel" keys with an appropriate value following. +The part list contains an arbitary number of lines. Each line is of the form: { "x": X, "y": Y, +"part": PARTID, ... } or { "x": X, "y": Y, "parts": [ PARTID1, ... ] } -In the second form, the line defines several parts at location X, Y. Each part is either defined by its PARTID string, or can be an object of the form - { "part": PARTID, ... } -with any of the optional keys "ammo", "ammo_types", "ammo_qty", or "fuel" as above. +In the first form, the line defines a single part at location X,Y of vehicle part type PARTID. It +can have the optional "ammo", "ammo_types", "ammo_qty", or "fuel" keys with an appropriate value +following. -Several different lines can have the same X, Y co-ordinates and each one adds additional parts to that location. Parts must be added in the correct order ie: A wheel hub must be added prior to the wheel, but after the frame. +In the second form, the line defines several parts at location X, Y. Each part is either defined by +its PARTID string, or can be an object of the form { "part": PARTID, ... } with any of the optional +keys "ammo", "ammo_types", "ammo_qty", or "fuel" as above. + +Several different lines can have the same X, Y co-ordinates and each one adds additional parts to +that location. Parts must be added in the correct order ie: A wheel hub must be added prior to the +wheel, but after the frame. ### Items list -The items list contains an arbitrary number of lines. Each line is of the form: - { "x": X, "y": Y, TYPE: DATA }, -and describes the items that may spawn at that location. -TYPE and DATA may be one of: + +The items list contains an arbitrary number of lines. Each line is of the form: { "x": X, "y": Y, +TYPE: DATA }, and describes the items that may spawn at that location. TYPE and DATA may be one of: + ```C++ "items": "itemid" // single item of that type "items": [ "itemid1", "itemid2", ... ] // all the items in the array @@ -63,6 +69,8 @@ TYPE and DATA may be one of: // whether the group is a collection or distribution "item_groups": [ "groupid1", "groupid2" ... ] // one or more items for each group ``` -the optional keyword "chance" provides an X in 100 chance that a particular item definition will spawn. + +the optional keyword "chance" provides an X in 100 chance that a particular item definition will +spawn. Multiple lines of items may share the same X and Y values. diff --git a/doc/VITAMIN.md b/doc/VITAMIN.md index 2abcb854a270..363522a34b34 100644 --- a/doc/VITAMIN.md +++ b/doc/VITAMIN.md @@ -18,59 +18,79 @@ "disease_excess": [ [ 10, 19 ], [ 20, 29 ], [ 30, 40 ] ] }, ``` + ### `id` + Mandatory. The id of the vitamin. ### `type` + Mandatory. Must be `vitamin`. ### `vit_type` + The type of the vitamin. Valid values are: #### `vitamin` -When simplified nutrition is enabled, this vitamin will not be added to any items and any time the game attempts to retrieve it from the player it will give 0. -Only nutritional vitamins should have this type. + +When simplified nutrition is enabled, this vitamin will not be added to any items and any time the +game attempts to retrieve it from the player it will give 0. Only nutritional vitamins should have +this type. #### `toxin` + This is some toxic chemical or component. This currently has no effect. #### `drug` + This is a drug. This currently has no effect. #### `counter` -This is a counter for something, that is neither a toxin, vitamin, or drug. This currently has no effect. + +This is a counter for something, that is neither a toxin, vitamin, or drug. This currently has no +effect. ### `name` -What the vitamin shows up as where vitamins are displayed, such as the vitamins display in the item menu. + +What the vitamin shows up as where vitamins are displayed, such as the vitamins display in the item +menu. ### `deficiency` + The id of an effect that is triggered by a deficiency of this vitamin. ### `excess` + The id of an effect that is triggered by a excess of this vitamin. ### `min` + The smallest amount of this vitamin that the player can have. ### `max` + The highest amount of this vitamin that the avatar can have. ### `rate` + How long it takes to lose one unit of this vitamin. ### `flags` + An array of string flags, see the flags section below for valid ones ### `disease` -What the thresholds of deficiency of this vitamin are. -Each pair in the list determines the start and end points of that tier of deficiency. -Each tier of deficiency corresponds to the intensity level of the effect defined in `deficiency`. + +What the thresholds of deficiency of this vitamin are. Each pair in the list determines the start +and end points of that tier of deficiency. Each tier of deficiency corresponds to the intensity +level of the effect defined in `deficiency`. ### `disease_excess` -What the thresholds of excess of this vitamin are. -Each pair in the list determines the start and end points of that tier of excess. -Each tier of excess corresponds to the intensity level of the effect defined in `excess`. + +What the thresholds of excess of this vitamin are. Each pair in the list determines the start and +end points of that tier of excess. Each tier of excess corresponds to the intensity level of the +effect defined in `excess`. ## flags -- ```NO_DISPLAY``` - This vitamin will not be shown when examining a food +- `NO_DISPLAY` - This vitamin will not be shown when examining a food diff --git a/doc/WEATHER_TYPE.md b/doc/WEATHER_TYPE.md index b5e699b1126a..14cb84205926 100644 --- a/doc/WEATHER_TYPE.md +++ b/doc/WEATHER_TYPE.md @@ -1,98 +1,100 @@ ## Weather_type -Weather type specifies conditions under which it can occur -(temperature, humidity, pressure, windpower, time of day, etc.) -and what effects it causes on the game world and reality bubble. +Weather type specifies conditions under which it can occur (temperature, humidity, pressure, +windpower, time of day, etc.) and what effects it causes on the game world and reality bubble. -When selecting weather type, the game goes over the list defined in region settings -and selects the last entry that is considered eligible under current conditions. -If none of the entries are eligible, invalid weather type `"none"` will be used. +When selecting weather type, the game goes over the list defined in region settings and selects the +last entry that is considered eligible under current conditions. If none of the entries are +eligible, invalid weather type `"none"` will be used. ### Fields -| Identifier | Description -|--- |--- -| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. -| name | (_mandatory_) In-game name displayed. -| color | (_mandatory_) Color of in-game name. -| glyph | (_mandatory_) Glyph used on overmap. -| map_color | (_mandatory_) Color of overmap glyph. -| ranged_penalty | (_mandatory_) Penalty to ranged attacks. -| sight_penalty | (_mandatory_) Sight penalty, aka multiplier to tile transparency. -| light_modifier | (_mandatory_) Flat bonus to ambient light. -| sound_attn | (_mandatory_) Sound attenuation (flat reduction to volume). -| dangerous | (_mandatory_) If true, prompts for activity interrupt. -| precip | (_mandatory_) Amount of associated precipitation. Valid values are: `none`, `very_light`, `light` and `heavy`. -| rains | (_mandatory_) Whether said precipitation falls as rain. -| acidic | (_optional_) Whether said precipitation is acidic. -| sound_category | (_optional_) Sound effects to play. Valid values are: `silent`, `drizzle`, `rainy`, `thunder`, `flurries`, `snowstorm` and `snow`. -| sun_intensity | (_mandatory_) Sunlight intensity. Valid values are: `none`, `light`, `normal`, and `high`. Normal and high are considered "direct sunlight". -| weather_animation | (_optional_) Weather animation in reality bubble. [Details](#weather_animation) -| effects | (_optional_) `[string, int]` pair array for the effects the weather causes. [Details](#effects) -| requirements | (_optional_) Conditions under which this weather type will be eligible to be selected. [Details](#requirements) +| Identifier | Description | +| ----------------- | -------------------------------------------------------------------------------------------------------------------------------------------- | +| id | (_mandatory_) Unique ID. Must be one continuous word, use underscores if necessary. | +| name | (_mandatory_) In-game name displayed. | +| color | (_mandatory_) Color of in-game name. | +| glyph | (_mandatory_) Glyph used on overmap. | +| map_color | (_mandatory_) Color of overmap glyph. | +| ranged_penalty | (_mandatory_) Penalty to ranged attacks. | +| sight_penalty | (_mandatory_) Sight penalty, aka multiplier to tile transparency. | +| light_modifier | (_mandatory_) Flat bonus to ambient light. | +| sound_attn | (_mandatory_) Sound attenuation (flat reduction to volume). | +| dangerous | (_mandatory_) If true, prompts for activity interrupt. | +| precip | (_mandatory_) Amount of associated precipitation. Valid values are: `none`, `very_light`, `light` and `heavy`. | +| rains | (_mandatory_) Whether said precipitation falls as rain. | +| acidic | (_optional_) Whether said precipitation is acidic. | +| sound_category | (_optional_) Sound effects to play. Valid values are: `silent`, `drizzle`, `rainy`, `thunder`, `flurries`, `snowstorm` and `snow`. | +| sun_intensity | (_mandatory_) Sunlight intensity. Valid values are: `none`, `light`, `normal`, and `high`. Normal and high are considered "direct sunlight". | +| weather_animation | (_optional_) Weather animation in reality bubble. [Details](#weather_animation) | +| effects | (_optional_) `[string, int]` pair array for the effects the weather causes. [Details](#effects) | +| requirements | (_optional_) Conditions under which this weather type will be eligible to be selected. [Details](#requirements) | ### weather_animation + All members are mandatory. -| Identifier | Description -|--- |--- -| factor | Display density: 0 is none, 1 will blot out the screen. -| glyph | Glyph to use in ASCII mode. -| color | Glyph color. -| tile | Graphical tile to use in TILES mode. +| Identifier | Description | +| ---------- | ------------------------------------------------------- | +| factor | Display density: 0 is none, 1 will blot out the screen. | +| glyph | Glyph to use in ASCII mode. | +| color | Glyph color. | +| tile | Graphical tile to use in TILES mode. | ### effects + `int` here is effect intensity. -| Identifier | Description -|--- |--- -| wet | wets player by `int` amount -| thunder | thunder sound with chance 1 in `int` -| lightening | 1 in `int` chance of sound plus message and possible super charging electric fields -| light_acid | causes pain unless waterproof -| acid_rain | causes more pain unless waterproof +| Identifier | Description | +| ---------- | ----------------------------------------------------------------------------------- | +| wet | wets player by `int` amount | +| thunder | thunder sound with chance 1 in `int` | +| lightening | 1 in `int` chance of sound plus message and possible super charging electric fields | +| light_acid | causes pain unless waterproof | +| acid_rain | causes more pain unless waterproof | ### requirements + All members are optional. -| Identifier | Description -|--- |--- -| pressure_min | Min pressure -| pressure_max | Max pressure -| humidity_min | Min humidity -| humidity_max | Max humidity -| temperature_min | Min temperature -| temperature_max | Max temperature -| windpower_min | Min windpower -| windpower_max | Max windpower -| humidity_and_pressure | If there are pressure and humidity requirements are they both required or just one -| acidic | Does this require acidic precipitation -| time | Time of day. Valid values are: day, night, and both. -| required_weathers | Will only be selected if conditions match for any of the specified types, i.e. rain can only happen if the conditions for clouds, light drizzle or drizzle are present. Required weathers should be "before" this one in the region weather list. +| Identifier | Description | +| --------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | +| pressure_min | Min pressure | +| pressure_max | Max pressure | +| humidity_min | Min humidity | +| humidity_max | Max humidity | +| temperature_min | Min temperature | +| temperature_max | Max temperature | +| windpower_min | Min windpower | +| windpower_max | Max windpower | +| humidity_and_pressure | If there are pressure and humidity requirements are they both required or just one | +| acidic | Does this require acidic precipitation | +| time | Time of day. Valid values are: day, night, and both. | +| required_weathers | Will only be selected if conditions match for any of the specified types, i.e. rain can only happen if the conditions for clouds, light drizzle or drizzle are present. Required weathers should be "before" this one in the region weather list. | ### Example ```json { - "id": "lightning", - "type": "weather_type", - "name": "Lightning Storm", - "color": "c_yellow", - "map_color": "h_yellow", - "glyph": "%", - "ranged_penalty": 4, - "sight_penalty": 1.25, - "light_modifier": -45, - "sound_attn": 8, - "dangerous": false, - "precip": "heavy", - "rains": true, - "acidic": false, - "effects": [ { "name": "thunder", "intensity": 50 }, { "name": "lightning", "intensity": 600 } ], - "tiles_animation": "weather_rain_drop", - "weather_animation": { "factor": 0.04, "color": "c_light_blue", "glyph": "," }, - "sound_category": "thunder", - "sun_intensity": "none", - "requirements": { "pressure_max": 990, "required_weathers": [ "thunder" ] } + "id": "lightning", + "type": "weather_type", + "name": "Lightning Storm", + "color": "c_yellow", + "map_color": "h_yellow", + "glyph": "%", + "ranged_penalty": 4, + "sight_penalty": 1.25, + "light_modifier": -45, + "sound_attn": 8, + "dangerous": false, + "precip": "heavy", + "rains": true, + "acidic": false, + "effects": [{ "name": "thunder", "intensity": 50 }, { "name": "lightning", "intensity": 600 }], + "tiles_animation": "weather_rain_drop", + "weather_animation": { "factor": 0.04, "color": "c_light_blue", "glyph": "," }, + "sound_category": "thunder", + "sun_intensity": "none", + "requirements": { "pressure_max": 990, "required_weathers": ["thunder"] } } ``` diff --git a/doc/melee_weapons/MELEE_BALANCE_SPREADSHEET.md b/doc/melee_weapons/MELEE_BALANCE_SPREADSHEET.md index 7b73ac3cd3e4..aa866ada87a9 100644 --- a/doc/melee_weapons/MELEE_BALANCE_SPREADSHEET.md +++ b/doc/melee_weapons/MELEE_BALANCE_SPREADSHEET.md @@ -1,69 +1,138 @@ ## Overview -This is documentation for the 'Melee Weapons Evaluation.md' spreadsheet. This is the spreadsheet that drove the 0.E experimental melee weapon rebalance project. The original spreadsheet is available as a [google doc](https://docs.google.com/spreadsheets/d/14eQIe4AO_f6OxCt1XcB4NLAs6-5R1wQW-ydZG0orYdY/edit#gid=1787713396) but the static copy is preserved in case stuff moves. -This is a complicated spreadsheet, with a lot of moving parts. The following are the tabs and the data flow: +This is documentation for the 'Melee Weapons Evaluation.md' spreadsheet. This is the spreadsheet +that drove the 0.E experimental melee weapon rebalance project. The original spreadsheet is +available as a +[google doc](https://docs.google.com/spreadsheets/d/14eQIe4AO_f6OxCt1XcB4NLAs6-5R1wQW-ydZG0orYdY/edit#gid=1787713396) +but the static copy is preserved in case stuff moves. + +This is a complicated spreadsheet, with a lot of moving parts. The following are the tabs and the +data flow: ### Raw -Raw was the initial data dump, taken from some October 2019 version of the 0.D experimental using mlangsdorf's usual mods (hence all the Blazemod stuff). Raw was slightly annoyed with some extra categories: -* Weapon Class - this is a simple numeric rating. 0 is not a weapon, 1 is an explosive device, 2 is a ranged weapon or gun, 3 is a tool that makes a poor weapon like a cooking pot, 4 is a helmet, 5 is a tool that makes a good weapon like a sledgehammer, 6 is an improvised or fake weapon, and 7 is an actual dedicated weapon -* Category - this is a categorization of items as weapons, to make it easier to compare similar weapons. Melee weapon categories are Ax, Ax2, Club, Club2, Flail, Flail2, Knife, Polearm, Spear, Staff, Shortsword, Sword, and Sword2. Categories that end with 2 are two-handed weapons. -* Acc - this is a recaluclation of weapon accuracy based on the accuracy factors below, because review of the data showed that a lot of weapons have accuracy values that are not supported by the criteria in GAME_BALANCE.md. -* Grip - the item's grip, as described in GAME_BALANCE.md -* Leng - the item's leng, as described in GAME_BALANCE.md -* Surf - the item's striking surface, as described in GAME_BALANCE.md. -* Bal - the item's balance, as described in GAME_BALANCE.md. Additional categories beyond Clumsy were added and assigned by eye. -### Filter -Filter takes the initial data from raw and a weapon class (in cell B1) and filters out items with a lower weapon class to make further analysis easier. +Raw was the initial data dump, taken from some October 2019 version of the 0.D experimental using +mlangsdorf's usual mods (hence all the Blazemod stuff). Raw was slightly annoyed with some extra +categories: + +- Weapon Class - this is a simple numeric rating. 0 is not a weapon, 1 is an explosive device, 2 is + a ranged weapon or gun, 3 is a tool that makes a poor weapon like a cooking pot, 4 is a helmet, 5 + is a tool that makes a good weapon like a sledgehammer, 6 is an improvised or fake weapon, and 7 + is an actual dedicated weapon +- Category - this is a categorization of items as weapons, to make it easier to compare similar + weapons. Melee weapon categories are Ax, Ax2, Club, Club2, Flail, Flail2, Knife, Polearm, Spear, + Staff, Shortsword, Sword, and Sword2. Categories that end with 2 are two-handed weapons. +- Acc - this is a recaluclation of weapon accuracy based on the accuracy factors below, because + review of the data showed that a lot of weapons have accuracy values that are not supported by the + criteria in GAME_BALANCE.md. +- Grip - the item's grip, as described in GAME_BALANCE.md +- Leng - the item's leng, as described in GAME_BALANCE.md +- Surf - the item's striking surface, as described in GAME_BALANCE.md. +- Bal - the item's balance, as described in GAME_BALANCE.md. Additional categories beyond Clumsy + were added and assigned by eye. -### New Formula -This calculates the new weapon evaluation formaula on the inital stats. This is complicated. - -The first 7 rows have some header data. The bulk of the calculation starts on row 8. +### Filter -The weapons were evaluated using a Strength 10, Dexterity 10, Perception 10 survivor with skill 4 in all weapons. The base hit, stat crit, skill crit, bash mult, cut mult, and stab mult values are derived from the relevant bits of src/melee.cpp. +Filter takes the initial data from raw and a weapon class (in cell B1) and filters out items with a +lower weapon class to make further analysis easier. -* Columnn A "Average" is the new weapon evaluation value for the weapon, on the edge of the sheet for easy reference. -* Columns B-J are the weapon's original stats, taken from the Raw tab via the Filter tab. -* Column K "roll_hit" is sum of the evaluator's base_hit and the weapon's acc. -* Column L "Wpn Crit" is weapon's contribution to critical hits. -* Columns M-N "3 Crit" and "2 Crit" are the chances of a triple and double critical hit occuring, based on skill, accuracy, and stats. -* Columns O-Q "Average Non-Crit" damage are the weapon's calculated average damage before armor for non-critical hits in each of the 3 categories. +### New Formula -All that is pretty straightforward. The next three blocks are where it gets complicated. Columns S-Z are repeated as AB-AI and AK-AR with different monster stats. -* Row S "Hits" is the expected number of hits per 1000 attacks, calculated against a normal distribution with a mean value of 5 * ( roll_hit - monster Dodge ) and a standard deviation of 25. -* Row T "Crit %s" is the percentage of those hits that should be critical hits. -* Row U "Dmg" is the average expected damage past armor. This is simply the sum of max( 0, damage type - armor amount ) for each of the 3 damage types. -* Row V "Crit" is the average expected critical damage past armor. This is the sum of the critical damage - armor amount for each of the three damage amounts, but the formula is substantially more complicated because the 3 damage types have different critical damage multipliers and reduce effective armor by different amounts on a critical. -* Rows W-Y repeat damage and critical damage, but for rapid strikes where the base damage is multiplied by 2/3rds. -* Row Z "Dmg/Turn" is either: -** 100 * ( Dmg * ( Hits - num crits ) + Crit Dmg * ( num hits ) ) / ( 1000 * Moves ) - ie, sum of damage per hit for each normal hit + crit damage for each critical hit divided by the number of moves in 1000 attacks, multiplied by 100 moves/second, OR -** 100 * ( Dmg * ( Hits - num crits ) / 2 + Crit Dmg * ( num hits ) / 2 + rapid strike Dmg * ( Hits - num crits ) / 2 + rapid strike Crit Dmg * ( num hits ) / 2 ) / ( 1000 - ( hits / 2 ) * Moves + Hits * 0.33 * Moves ) - same as above, but accounting for rapid strike reduced damage and movement cost. +This calculates the new weapon evaluation formaula on the inital stats. This is complicated. + +The first 7 rows have some header data. The bulk of the calculation starts on row 8. + +The weapons were evaluated using a Strength 10, Dexterity 10, Perception 10 survivor with skill 4 in +all weapons. The base hit, stat crit, skill crit, bash mult, cut mult, and stab mult values are +derived from the relevant bits of src/melee.cpp. + +- Columnn A "Average" is the new weapon evaluation value for the weapon, on the edge of the sheet + for easy reference. +- Columns B-J are the weapon's original stats, taken from the Raw tab via the Filter tab. +- Column K "roll_hit" is sum of the evaluator's base_hit and the weapon's acc. +- Column L "Wpn Crit" is weapon's contribution to critical hits. +- Columns M-N "3 Crit" and "2 Crit" are the chances of a triple and double critical hit occuring, + based on skill, accuracy, and stats. +- Columns O-Q "Average Non-Crit" damage are the weapon's calculated average damage before armor for + non-critical hits in each of the 3 categories. + +All that is pretty straightforward. The next three blocks are where it gets complicated. Columns S-Z +are repeated as AB-AI and AK-AR with different monster stats. + +- Row S "Hits" is the expected number of hits per 1000 attacks, calculated against a normal + distribution with a mean value of 5 * ( roll_hit - monster Dodge ) and a standard deviation of 25. +- Row T "Crit %s" is the percentage of those hits that should be critical hits. +- Row U "Dmg" is the average expected damage past armor. This is simply the sum of max( 0, damage + type - armor amount ) for each of the 3 damage types. +- Row V "Crit" is the average expected critical damage past armor. This is the sum of the critical + damage - armor amount for each of the three damage amounts, but the formula is substantially more + complicated because the 3 damage types have different critical damage multipliers and reduce + effective armor by different amounts on a critical. +- Rows W-Y repeat damage and critical damage, but for rapid strikes where the base damage is + multiplied by 2/3rds. +- Row Z "Dmg/Turn" is either: ** 100 * ( Dmg * ( Hits - num crits ) + Crit Dmg * ( num hits ) ) / ( + 1000 * Moves ) - ie, sum of damage per hit for each normal hit + crit damage for each critical hit + divided by the number of moves in 1000 attacks, multiplied by 100 moves/second, OR ** 100 * ( + Dmg * ( Hits - num crits ) / 2 + Crit Dmg * ( num hits ) / 2 + rapid strike Dmg * ( Hits - num + crits ) / 2 + rapid strike Crit Dmg * ( num hits ) / 2 ) / ( 1000 - ( hits / 2 ) * Moves + Hits * + 0.33 * Moves ) - same as above, but accounting for rapid strike reduced damage and movement cost. Finally, -* Column AT "Weapon" is a repeat of the weapon name for refernce -* Column Au "Value" is the average of columns Z, AI, and AR, multiplied by 1.5 for Reach 2 weapons and 1.75 for Reach 3 weapons. + +- Column AT "Weapon" is a repeat of the weapon name for refernce +- Column Au "Value" is the average of columns Z, AI, and AR, multiplied by 1.5 for Reach 2 weapons + and 1.75 for Reach 3 weapons. ### New Formula Sorted -This compares the old weapon values versus the values from the new formula, and sorts weapons by decreasing new value by weapon category to make it easier to spot weapons that are unsually good (I'm looking at you, broadsword) or bad for their category. + +This compares the old weapon values versus the values from the new formula, and sorts weapons by +decreasing new value by weapon category to make it easier to spot weapons that are unsually good +(I'm looking at you, broadsword) or bad for their category. ### Proposed Values -This repeats the New Formula tab, except that Columns C-J were copied over and pasted as values, and then adjusted to make the numbers nice. -* Accuracy was adjusted to the new values based on grip, length, striking surface, and balance from the Raw tab. That means a bunch of previously accurate weapons like bionic claws got a nerf, and inappropriately inaccurate weapons like katanas got a buff. -* Weapons in the same category were generally adjusted to have roughly the same evaluation, though with different values. In general, European weapons get more of their damage from bash and less from cut, and are often heavier and slower, than Asian weapons. This is a little arbitrary and not entirely realistic, but everyone seems to expect it. As a case in point, the Japanese two-handed sword "nodachi" has 164 attack speed, bash 6, and cut 47, while the European two-handed sword zweihander has 169 attack speed, base 18, cut 39. They both have values of about 26. -* Inferior weapons got a 1 step penalty in balance compared to the real weapon, and half of the cut/pierce damage is moved to bash, and the cut/pierce damage is 1/4th's the real weapons. Ie, an inferior pike does Bash 30, Stab 11 to a pike's Bash 8, Stab 44. -* Fake weapons are as badly balanced as the inferior version of a weapon, but are basically blunt so the striking surface usually got upgraded to "every", ironically making them as accurate or more accurate than the real version of the weapon. Bash damage was halved from the inferior version, and cut/pierce damage was again reduced to 1/4th of the inferior version, which is 1/16th the real version. A fake pike does Bash 15, Stab 3. -* A lot of weapons got damage boosts to bring up their evaluated value. A lot of low damage weapons with rapid strike were being drastically overvalued, but the damage past armor tests showed that rapid strike often just lets you bounce off armor twice as fast. -* Spears got some rough formula for pierce damage based on weight that I can't recover anymore, but in general the differences between spears are more minor than they used to be. -* Polearms got the same rough damage as Ax2 at range 2, but got a separate balance line at range 1 with the raw damage reduced by 0.7. This makes polearms very impressive at range, but slightly worse than quarterstaffs against adjacent targets. +This repeats the New Formula tab, except that Columns C-J were copied over and pasted as values, and +then adjusted to make the numbers nice. + +- Accuracy was adjusted to the new values based on grip, length, striking surface, and balance from + the Raw tab. That means a bunch of previously accurate weapons like bionic claws got a nerf, and + inappropriately inaccurate weapons like katanas got a buff. +- Weapons in the same category were generally adjusted to have roughly the same evaluation, though + with different values. In general, European weapons get more of their damage from bash and less + from cut, and are often heavier and slower, than Asian weapons. This is a little arbitrary and not + entirely realistic, but everyone seems to expect it. As a case in point, the Japanese two-handed + sword "nodachi" has 164 attack speed, bash 6, and cut 47, while the European two-handed sword + zweihander has 169 attack speed, base 18, cut 39. They both have values of about 26. +- Inferior weapons got a 1 step penalty in balance compared to the real weapon, and half of the + cut/pierce damage is moved to bash, and the cut/pierce damage is 1/4th's the real weapons. Ie, an + inferior pike does Bash 30, Stab 11 to a pike's Bash 8, Stab 44. +- Fake weapons are as badly balanced as the inferior version of a weapon, but are basically blunt so + the striking surface usually got upgraded to "every", ironically making them as accurate or more + accurate than the real version of the weapon. Bash damage was halved from the inferior version, + and cut/pierce damage was again reduced to 1/4th of the inferior version, which is 1/16th the real + version. A fake pike does Bash 15, Stab 3. +- A lot of weapons got damage boosts to bring up their evaluated value. A lot of low damage weapons + with rapid strike were being drastically overvalued, but the damage past armor tests showed that + rapid strike often just lets you bounce off armor twice as fast. +- Spears got some rough formula for pierce damage based on weight that I can't recover anymore, but + in general the differences between spears are more minor than they used to be. +- Polearms got the same rough damage as Ax2 at range 2, but got a separate balance line at range 1 + with the raw damage reduced by 0.7. This makes polearms very impressive at range, but slightly + worse than quarterstaffs against adjacent targets. ### Poposed Values Sorted + This is another comparison tab like New Formula Sorted, but used the data from Proposed Values. ### Comparison + This is a summary tab. -In columns A-P, each weapon from the filter tab gets it's current and proposed stats, it's original value, value under the new formula, and value under the new formula using the proposed values. For proposed values, values that improved are highlighted in green and those that got worse are in red. Ideally, this will make it easy to compare changes and catch mistakes. +In columns A-P, each weapon from the filter tab gets it's current and proposed stats, it's original +value, value under the new formula, and value under the new formula using the proposed values. For +proposed values, values that improved are highlighted in green and those that got worse are in red. +Ideally, this will make it easy to compare changes and catch mistakes. -Columns S-AH repeat the process, but cells S1, T1, U1, and V1 can be used to specify category names, and then the subtotal shows a selected subset of weapons that match those categories. This simplifies comparing things. +Columns S-AH repeat the process, but cells S1, T1, U1, and V1 can be used to specify category names, +and then the subtotal shows a selected subset of weapons that match those categories. This +simplifies comparing things. diff --git a/lang/concat_pot_files.py b/lang/concat_pot_files.py index 71c3f830e103..837ad5af914e 100755 --- a/lang/concat_pot_files.py +++ b/lang/concat_pot_files.py @@ -18,13 +18,13 @@ destination_file = args[2] if not os.path.isfile(source_file_1): - print("Error: Couldn't find file '{}'.".format(source_file_1)) + print(f"Error: Couldn't find file '{source_file_1}'.") exit(1) if not os.path.isfile(source_file_2): - print("Error: Couldn't find file '{}'.".format(source_file_2)) + print(f"Error: Couldn't find file '{source_file_2}'.") exit(1) -print("==> Merging '{}' and '{}' into '{}".format(source_file_1, source_file_2, destination_file)) +print(f"==> Merging '{source_file_1}' and '{source_file_2}' into '{destination_file}") pot1 = polib.pofile(source_file_1) pot2 = polib.pofile(source_file_2) diff --git a/lang/extract_json_strings.py b/lang/extract_json_strings.py index eb1c014de870..7cd9d7e4e795 100755 --- a/lang/extract_json_strings.py +++ b/lang/extract_json_strings.py @@ -4,7 +4,6 @@ "Use dedup_pot_file.py to resolve them." import time -import polib import json import os import itertools @@ -13,6 +12,21 @@ from sys import platform from copy import deepcopy +try: + import polib +except: + print("You need 'polib' module installed for the script to work.") + exit(1) + +try: + import luaparser +except: + print("You need 'luaparser' module installed for the script to work.") + exit(1) + +from luaparser import ast +from luaparser import astnodes + # Must parse command line arguments here # 'options' variable is referenced in our defined functions below @@ -48,7 +62,7 @@ def __init__(self, msg, item): self.item = item def __str__(self): - return ("---\nJSON error\n{0}\n--- JSON Item:\n{1}\n---".format(self.msg, self.item)) + return (f"---\nJSON error\n{self.msg}\n--- JSON Item:\n{self.item}\n---") git_files_list = {os.path.normpath(i) for i in { ".", @@ -197,6 +211,7 @@ def warning_supressed(filename): "MAGAZINE", "MONSTER", "PET_ARMOR", + "SPECIES", "TOOL", "TOOLMOD", "TOOL_ARMOR", @@ -207,7 +222,7 @@ def warning_supressed(filename): all_genders = ["f", "m", "n"] def gender_options(subject): - return [subject + ":" + g for g in all_genders] + return [f"{subject}:{g}" for g in all_genders] ## ## SPECIALIZED EXTRACTION FUNCTIONS @@ -261,7 +276,7 @@ def extract_material(state, item): writestr(state, item["dmg_adj"][3]) wrote = True if not wrote and not "copy-from" in item: - print("WARNING: {}: no mandatory field in item: {}".format(state.current_source_file, item)) + print(f"WARNING: {state.current_source_file}: no mandatory field in item: {item}") def extract_martial_art(state, item): @@ -272,10 +287,10 @@ def extract_martial_art(state, item): name = item["id"] if "description" in item: writestr(state, item["description"], - comment="Description for martial art '{}'".format(name)) + comment=f"Description for martial art '{name}'") if "initiate" in item: writestr(state, item["initiate"], format_strings=True, - comment="Initiate message for martial art '{}'".format(name)) + comment=f"Initiate message for martial art '{name}'") onhit_buffs = item.get("onhit_buffs", list()) static_buffs = item.get("static_buffs", list()) onmove_buffs = item.get("onmove_buffs", list()) @@ -284,9 +299,9 @@ def extract_martial_art(state, item): for buff in buffs: writestr(state, buff["name"]) if buff["name"] == item["name"]: - c="Description of buff for martial art '{}'".format(name) + c=f"Description of buff for martial art '{name}'" else: - c="Description of buff '{}' for martial art '{}'".format(buff["name"], name) + c=f"Description of buff '{buff['name']}' for martial art '{name}'" writestr(state, buff["description"], comment=c) @@ -299,7 +314,7 @@ def extract_effect_type(state, item): for nm_desc in zip(ctxt_name, item.get("desc", ())): writestr(state, nm_desc[0]) writestr(state, nm_desc[1], format_strings=True, - comment="Description of effect '{}'.".format(nm_desc[0])) + comment=f"Description of effect '{nm_desc[0]}'.") else: for i in ctxt_name: writestr(state, i) @@ -316,7 +331,7 @@ def extract_effect_type(state, item): writestr(state, msg, format_strings=True) else: writestr(state, msg, format_strings=True, - comment="Apply message for effect(s) '{}'.".format(', '.join(name))) + comment=f"Apply message for effect(s) '{', '.join(name)}'.") # remove_message msg = item.get("remove_message") @@ -324,7 +339,7 @@ def extract_effect_type(state, item): writestr(state, msg, format_strings=True) else: writestr(state, msg, format_strings=True, - comment="Remove message for effect(s) '{}'.".format(', '.join(name))) + comment=f"Remove message for effect(s) '{', '.join(name)}'.") # miss messages msg = item.get("miss_messages", ()) @@ -334,7 +349,7 @@ def extract_effect_type(state, item): else: for m in msg: writestr(state, m[0], - comment="Miss message for effect(s) '{}'.".format(', '.join(name))) + comment=f"Miss message for effect(s) '{', '.join(name)}'.") msg = item.get("decay_messages", ()) if not name: for m in msg: @@ -342,14 +357,14 @@ def extract_effect_type(state, item): else: for m in msg: writestr(state, m[0], - comment="Decay message for effect(s) '{}'.".format(', '.join(name))) + comment=f"Decay message for effect(s) '{', '.join(name)}'.") # speed_name if "speed_name" in item: if not name: writestr(state, item.get("speed_name")) else: - writestr(state, item.get("speed_name"), comment="Speed name of effect(s) '{}'.".format(', '.join(name))) + writestr(state, item.get("speed_name"), comment=f"Speed name of effect(s) '{', '.join(name)}'.") # apply and remove memorial messages. msg = item.get("apply_memorial_log") @@ -358,18 +373,18 @@ def extract_effect_type(state, item): writestr(state, msg, context="memorial_female") else: writestr(state, msg, context="memorial_male", - comment="Male memorial apply log for effect(s) '{}'.".format(', '.join(name))) + comment=f"Male memorial apply log for effect(s) '{', '.join(name)}'.") writestr(state, msg, context="memorial_female", - comment="Female memorial apply log for effect(s) '{}'.".format(', '.join(name))) + comment=f"Female memorial apply log for effect(s) '{', '.join(name)}'.") msg = item.get("remove_memorial_log") if not name: writestr(state, msg, context="memorial_male") writestr(state, msg, context="memorial_female") else: writestr(state, msg, context="memorial_male", - comment="Male memorial remove log for effect(s) '{}'.".format(', '.join(name))) + comment=f"Male memorial remove log for effect(s) '{', '.join(name)}'.") writestr(state, msg, context="memorial_female", - comment="Female memorial remove log for effect(s) '{}'.".format(', '.join(name))) + comment=f"Female memorial remove log for effect(s) '{', '.join(name)}'.") def extract_gun(state, item): @@ -443,9 +458,9 @@ def extract_profession(state, item): comment_f = entry_f["str"] if "description" in item: writestr(state, add_context(item["description"], "prof_desc_male"), - comment="Profession (male {}) description".format(comment_m)) + comment=f"Profession (male {comment_m}) description") writestr(state, add_context(item["description"], "prof_desc_female"), - comment="Profession (female {}) description".format(comment_f)) + comment=f"Profession (female {comment_f}) description") def extract_scenario(state, item): @@ -454,28 +469,28 @@ def extract_scenario(state, item): writestr(state, name, context="scenario_male", - comment="Name for scenario '{}' for a male character".format(name)) + comment=f"Name for scenario '{name}' for a male character") writestr(state, name, context="scenario_female", - comment="Name for scenario '{}' for a female character".format(name)) + comment=f"Name for scenario '{name}' for a female character") if name: msg = item.get("description") if msg: writestr(state, msg, context="scen_desc_male", - comment="Description for scenario '{}' for a male character.".format(name)) + comment=f"Description for scenario '{name}' for a male character.") writestr(state, msg, context="scen_desc_female", - comment="Description for scenario '{}' for a female character.".format(name)) + comment=f"Description for scenario '{name}' for a female character.") msg = item.get("start_name") if msg: writestr(state, msg, context="start_name", - comment="Starting location for scenario '{}'.".format(name)) + comment=f"Starting location for scenario '{name}'.") else: for f in ["description", "start_name"]: found = item.get(f, None) @@ -584,7 +599,7 @@ def extract_talk_effects(state, effects): for eff in effects: if type(eff) == dict: if "u_buy_monster" in eff and "name" in eff: - writestr(state, eff["name"], comment="Nickname for creature '{}'".format(eff["u_buy_monster"])) + writestr(state, eff["name"], comment=f"Nickname for creature '{eff['u_buy_monster']}'") def extract_talk_response(state, response): @@ -630,7 +645,7 @@ def extract_technique(state, item): def extract_trap(state, item): writestr(state, item["name"]) if "vehicle_data" in item and "sound" in item["vehicle_data"]: - writestr(state, item["vehicle_data"]["sound"], comment="Trap-vehicle collision message for trap '{}'".format(item["name"])) + writestr(state, item["vehicle_data"]["sound"], comment=f"Trap-vehicle collision message for trap '{item['name']}'") def extract_missiondef(state, item): @@ -639,7 +654,7 @@ def extract_missiondef(state, item): raise WrongJSONItem("JSON item don't contain 'name' field", item) writestr(state, item_name) if "description" in item: - writestr(state, item["description"], comment="Description for mission '{}'".format(item_name)) + writestr(state, item["description"], comment=f"Description for mission '{item_name}'") if "dialogue" in item: dialogue = item.get("dialogue") if "describe" in dialogue: @@ -684,7 +699,7 @@ def extract_mutation(state, item): found = item.get(f) # Need that check due format string argument if found is not None: - writestr(state, found, comment="Description for {}".format(item_name_or_id)) + writestr(state, found, comment=f"Description for {item_name_or_id}") if "attacks" in item: attacks = item.get("attacks") @@ -721,13 +736,13 @@ def extract_mutation_category(state, item): found = item.get(f) # Need that check due format string argument if found is not None: - writestr(state, found, comment="Mutation class: {} {}".format(item_name, f)) + writestr(state, found, comment=f"Mutation class: {item_name} {f}") found = item.get("memorial_message") writestr(state, found, context="memorial_male", - comment="Mutation class: {} Male memorial messsage".format(item_name)) + comment=f"Mutation class: {item_name} Male memorial messsage") writestr(state, found, context="memorial_female", - comment="Mutation class: {} Female memorial messsage".format(item_name)) + comment=f"Mutation class: {item_name} Female memorial messsage") def extract_vehspawn(state, item): @@ -756,7 +771,7 @@ def extract_recipe_category(state, item): continue subcat_name = subcat.split('_')[2] writestr(state, subcat_name, - comment="Crafting recipes subcategory of '{}' category".format(cat_name)) + comment=f"Crafting recipes subcategory of '{cat_name}' category") def extract_gate(state, item): @@ -764,7 +779,7 @@ def extract_gate(state, item): for (k, v) in sorted(messages.items(), key=lambda x: x[0]): writestr(state, v, - comment="'{}' action message of some gate object.".format(k)) + comment=f"'{k}' action message of some gate object.") def extract_field_type(state, item): @@ -784,19 +799,19 @@ def extract_ter_furn_transform(state, item): def extract_skill_display_type(state, item): - writestr(state, item["display_string"], comment="Display string for skill display type '{}'".format(item["id"])) + writestr(state, item["display_string"], comment=f"Display string for skill display type '{item['id']}'") def extract_fault(state, item): writestr(state, item["name"]) - writestr(state, item["description"], comment="Description for fault '{}'".format(item["name"])) + writestr(state, item["description"], comment=f"Description for fault '{item['name']}'") for method in item["mending_methods"]: if "name" in method: - writestr(state, method["name"], comment="Name of mending method for fault '{}'".format(item["name"])) + writestr(state, method["name"], comment=f"Name of mending method for fault '{item['name']}'") if "description" in method: - writestr(state, method["description"], comment="Description for mending method '{}' of fault '{}'".format(method["name"], item["name"])) + writestr(state, method["description"], comment=f"Description for mending method '{method['name']}' of fault '{item['name']}'") if "success_msg" in method: - writestr(state, method["success_msg"], format_strings=True, comment="Success message for mending method '{}' of fault '{}'".format(method["name"], item["name"])) + writestr(state, method["success_msg"], format_strings=True, comment=f"Success message for mending method '{method['name']}' of fault '{item['name']}'") def extract_snippet(state, item): @@ -860,7 +875,7 @@ def add_context(entry, ctxt): entry = deepcopy(entry) if type(entry) == dict: if "ctxt" in entry: - entry["ctxt"] += "|" + ctxt + entry["ctxt"] += f"|{ctxt}" else: entry["ctxt"] = ctxt return entry @@ -868,6 +883,29 @@ def add_context(entry, ctxt): return {"str": entry, "ctxt": ctxt} +def writestr_basic(state, msgid, msgid_plural, msgctxt, comment, check_c_format): + flags = [] + if check_c_format and ("%" in msgid or (msgid_plural is not None and "%" in msgid_plural)): + flags.append('c-format') + + # Using None here because we neither know nor care about exact line numbers + occurrences = [(state.current_source_file, None)] + + if comment: + # Append `~ ` to help translators distinguish between comments + comment = f"~ {comment}" + + entry = polib.POEntry( + msgid=msgid, + msgid_plural=msgid_plural, + msgctxt=msgctxt, + comment=comment, + flags=flags, + occurrences=occurrences + ) + state.po_entries.append(entry) + + def writestr(state, string, context=None, format_strings=False, comment=None, pl_fmt=False): "Write the string to POT." if type(string) is list: @@ -879,7 +917,7 @@ def writestr(state, string, context=None, format_strings=False, comment=None, pl if comment is None: comment = string["//~"] else: - comment = "{}\n{}".format(comment, string["//~"]) + comment = f"{comment}\n{string['//~']}" context = string.get( "ctxt" ) str_pl = None if pl_fmt: @@ -889,7 +927,7 @@ def writestr(state, string, context=None, format_strings=False, comment=None, pl str_pl = string["str_sp"] else: # no "str_pl" entry in json, assuming regular plural form as in translations.cpp - str_pl = "{}s".format(string["str"]) + str_pl = f"{string['str']}s" elif "str_pl" in string or "str_sp" in string: raise WrongJSONItem("ERROR: 'str_pl' and 'str_sp' not supported here", string) if "str" in string: @@ -905,7 +943,7 @@ def writestr(state, string, context=None, format_strings=False, comment=None, pl str_singular = string if pl_fmt: # no "str_pl" entry in json, assuming regular plural form as in translations.cpp - str_pl = "{}s".format(string) + str_pl = f"{string}s" else: str_pl = None elif string is None: @@ -913,26 +951,7 @@ def writestr(state, string, context=None, format_strings=False, comment=None, pl else: raise WrongJSONItem("ERROR: value is not a string, dict, list, or None", string) - flags = [] - if format_strings and ("%" in str_singular or (str_pl is not None and "%" in str_pl)): - flags.append('c-format') - - # Using None here because we neither know nor care about exact line numbers - occurrences = [(state.current_source_file, None)] - - if comment: - # Append `~ ` to help translators distinguish between comments - comment = '~ ' + comment - - entry = polib.POEntry( - msgid=str_singular, - msgid_plural=str_pl, - msgctxt=context, - comment=comment, - flags=flags, - occurrences=occurrences - ) - state.po_entries.append(entry) + writestr_basic(state, str_singular, str_pl, context, comment, format_strings) use_action_msgs = { @@ -977,7 +996,7 @@ def extract_use_action_msgs(state, use_action, it_name): if type(use_action) is dict and f in use_action: if it_name: writestr(state, use_action[f], - comment="Use action {} for {}.".format(f, it_name)) + comment=f"Use action {f} for {it_name}.") # Recursively check sub objects as they may contain more messages. if type(use_action) is list: for i in use_action: @@ -990,9 +1009,9 @@ def extract_use_action_msgs(state, use_action, it_name): known_types = ignorable | extract_specials.keys() | automatically_convertible -def extract(state, item): +def extract_json(state, item): """Find any extractable strings in the given json object, - and write them to the appropriate file.""" + and write them to the PO file provided by the state.""" if not "type" in item: return object_type = item["type"] @@ -1003,9 +1022,9 @@ def extract(state, item): extract_specials[object_type](state, item) return elif object_type not in automatically_convertible: - raise WrongJSONItem("ERROR: Unrecognized object type '{}'!".format(object_type), item) + raise WrongJSONItem(f"ERROR: Unrecognized object type '{object_type}'!", item) if object_type not in known_types: - print("WARNING: known_types does not contain object type '{}'".format(object_type)) + print(f"WARNING: known_types does not contain object type '{object_type}'") # Use mod id as project name if project name is not specified if object_type == "MOD_INFO" and not state.project_name: state.project_name = item.get("id") @@ -1034,12 +1053,12 @@ def extract(state, item): wrote = True if "conditional_names" in item: for cname in item["conditional_names"]: - c = "Conditional name for {} when {} matches {}".format(name, cname["type"], cname["condition"]) + c = f"Conditional name for {name} when {cname['type']} matches {cname['condition']}" writestr(state, cname["name"], comment=c, format_strings=True, pl_fmt=True) wrote = True if "description" in item: if name: - c = "Description for {}".format(name) + c = f"Description for {name}" else: c = None writestr(state, item["description"], comment=c) @@ -1051,7 +1070,7 @@ def extract(state, item): writestr(state, item["sound"]) wrote = True if "sound_description" in item: - writestr(state, item["sound_description"], comment="Description for the sound of spell '{}'".format(name)) + writestr(state, item["sound_description"], comment=f"Description for the sound of spell '{name}'") wrote = True if "snippet_category" in item and type(item["snippet_category"]) is list: # snippet_category is either a simple string (the category ident) @@ -1105,7 +1124,7 @@ def extract(state, item): for rech in relic_data["recharge_scheme"]: if "message" in rech: writestr(state, rech["message"], - comment="Relic recharge message for {} '{}'".format(object_type, name) + comment=f"Relic recharge message for {object_type} '{name}'" ) wrote = True if "text" in item: @@ -1116,7 +1135,7 @@ def extract(state, item): wrote = True if "message" in item: writestr(state, item["message"], format_strings=True, - comment="Message for {} '{}'".format(object_type, name) ) + comment=f"Message for {object_type} '{name}'" ) wrote = True if "messages" in item: for message in item["messages"]: @@ -1149,7 +1168,168 @@ def extract(state, item): wrote = True if not wrote and not "copy-from" in item: if not warning_supressed(state.current_source_file): - print("WARNING: {}: nothing translatable found in item: {}".format(state.current_source_file, item)) + print(f"WARNING: {state.current_source_file}: nothing translatable found in item: {item}") + + +def assert_num_args(node, args, n): + if len(args) != n: + raise Exception(f"invalid amount of arguments in translation call (found {len(args)}, expected {n}). Error source: {ast.to_lua_source(node)}") + + +def get_string_literal(node, args, pos): + if isinstance(args[pos], astnodes.String): + return args[pos].s + else: + raise Exception(f"argument to translation call should be string. Error source: {ast.to_lua_source(node)}") + + +class LuaComment: + def __init__(self, source, comment_node): + first_char = comment_node.first_token.start + last_char = comment_node.first_token.stop + text = source[first_char:last_char+1] + line = comment_node.first_token.line + source = comment_node.first_token.source + + self.is_trans_comment = self.__check_is_trans_comment(text) + self.text = self.__strip_comment(text) + self.line = line + self.source = source + self.used = False + + def mark_used(self): + self.used = True + + def __strip_comment(self, text): + if text.startswith("--[[") and text.endswith("]]"): + # Regular multiline comment + return text[4:len(text)-2].strip() + elif text.startswith("--~"): + # Translation comment + return text[3:].strip() + elif text.startswith("--"): + # Regular comment + return text[2:].strip() + else: + return text + + def __check_is_trans_comment(self, text): + return text.startswith("--~") + + +class LuaCallVisitor(ast.ASTVisitor): + def register_state(self, state): + self.state = state + + def load_comments(self, comments): + self.trans_comments = [] + self.regular_comments = [] + for comment in comments: + if comment.is_trans_comment: + self.trans_comments.append(comment) + else: + self.regular_comments.append(comment) + + def report_unused_comments(self): + for comment in self.trans_comments: + if not comment.used: + print(f"WARNING: unused translator comment at {self.state.current_source_file}:{comment.line}") + + def __find_trans_comments_before(self, line): + for comment in self.trans_comments: + if comment.line == line - 1: + comment.mark_used() + ret = self.__find_trans_comments_before( line - 1 ) + ret.append(comment.text) + return ret + return [] + + def __find_regular_comment_before(self, line): + for comment in self.regular_comments: + if comment.line == line - 1: + return comment + return None + + def __find_comment(self, line): + comments = self.__find_trans_comments_before(line) + if len(comments) != 0: + return '\n'.join(comments) + else: + comment = self.__find_regular_comment_before(line) + if comment: + print(f"WARNING: regular comment used when translation comment may be intended. Error source: {self.state.current_source_file}:{comment.line}") + return None + + def visit_Call(self, node): + found = False + if isinstance(node.func, astnodes.Name): + func_id = node.func.id + func_line = node.func.first_token.line + func_args = node.args + found = True + elif isinstance(node.func, astnodes.Index): + if isinstance(node.func.idx, astnodes.Name): + func_id = node.func.idx.id + func_line = node.func.idx.first_token.line + func_args = node.args + found = True + if not found: + return + write = False + msgctxt = None + msgid = None + msgid_plural = None + try: + if func_id == "gettext": + assert_num_args(node, func_args, 1) + msgid = get_string_literal(node, func_args, 0) + write = True + elif func_id == "pgettext": + assert_num_args(node, func_args, 2) + msgctxt = get_string_literal(node, func_args, 0) + msgid = get_string_literal(node, func_args, 1) + write = True + elif func_id == "vgettext": + assert_num_args(node, func_args, 3) + msgid = get_string_literal(node, func_args, 0) + msgid_plural = get_string_literal(node, func_args, 1) + write = True + elif func_id == "vpgettext": + assert_num_args(node, func_args, 4) + msgctxt = get_string_literal(node, func_args, 0) + msgid = get_string_literal(node, func_args, 1) + msgid_plural = get_string_literal(node, func_args, 2) + write = True + except Exception as E: + print(f"WARNING: {E}") + if write: + comment = self.__find_comment(func_line) + writestr_basic(self.state, msgid, msgid_plural, msgctxt, comment, check_c_format = True) + + +def extract_lua(state, source): + """Find any extractable strings in the given Lua source code, + and write them to the PO file provided by the state.""" + + tree = ast.parse(source) + + #print(ast.to_pretty_str(tree)) + + comments = [] + + for node in ast.walk(tree): + for comment_node in node.comments: + comments.append(LuaComment( source, comment_node )) + + for comment in comments: + if comment.is_trans_comment: + print(f"Line {comment.line}: {comment.text}") + + visitor = LuaCallVisitor() + visitor.register_state(state) + visitor.load_comments(comments) + visitor.visit(tree) + visitor.report_unused_comments() def log_verbose(msg): @@ -1157,51 +1337,72 @@ def log_verbose(msg): print(msg) -def extract_all_from_dir(state, json_dir): - """Extract strings from every json file in the specified directory, +def extract_all_from_dir(state, dir): + """Extract strings from every applicable file in the specified directory, recursing into any subdirectories.""" - allfiles = os.listdir(json_dir) + allfiles = os.listdir(dir) allfiles.sort() dirs = [] skiplist = [ os.path.normpath(".gitkeep") ] for f in allfiles: - full_name = os.path.join(json_dir, f) + full_name = os.path.join(dir, f) if os.path.isdir(full_name): if os.path.normpath(full_name) in ignore_dirs: - log_verbose("Skipping dir (ignored): {}".format(f)) + log_verbose(f"Skipping dir (ignored): {f}") else: dirs.append(f) elif f in skiplist: - log_verbose("Skipping file (skiplist): '{}'".format(f)) + log_verbose(f"Skipping file (skiplist): '{f}'") elif full_name in ignore_files: - log_verbose("Skipping file (ignored): '{}'".format(f)) + log_verbose(f"Skipping file (ignored): '{f}'") elif f.endswith(".json"): if not options.tracked_only or full_name in git_files_list: - extract_all_from_file(state, full_name) + extract_all_from_json_file(state, full_name) + else: + log_verbose(f"Skipping file (untracked): '{full_name}'") + elif f.endswith(".lua"): + if not options.tracked_only or full_name in git_files_list: + extract_all_from_lua_file(state, full_name) else: - log_verbose("Skipping file (untracked): '{}'".format(full_name)) + log_verbose(f"Skipping file (untracked): '{full_name}'") else: - log_verbose("Skipping file (not json): '{}'".format(f)) + log_verbose(f"Skipping file (not applicable): '{f}'") for d in dirs: - extract_all_from_dir(state, os.path.join(json_dir, d)) + extract_all_from_dir(state, os.path.join(dir, d)) -def extract_all_from_file(state, json_file): - "Extract translatable strings from every object in the specified file." +def extract_all_from_json_file(state, json_file): + "Extract translatable strings from every object in the specified JSON file." state.current_source_file = json_file - log_verbose("Loading {}".format(json_file)) + log_verbose(f"Loading {json_file}") with open(json_file, encoding="utf-8") as fp: jsondata = json.load(fp) # it's either an array of objects, or a single object try: if hasattr(jsondata, "keys"): - extract(state, jsondata) + extract_json(state, jsondata) else: for jsonobject in jsondata: - extract(state, jsonobject) + extract_json(state, jsonobject) except WrongJSONItem as E: - print("---\nFile: '{0}'".format(json_file)) + print(f"---\nFile: '{json_file}'") + print(E) + exit(1) + + +def extract_all_from_lua_file(state, lua_file): + "Extract translatable strings from lua code in the specified file." + state.current_source_file = lua_file + log_verbose(f"Loading {lua_file}") + + with open(lua_file, encoding="utf-8") as fp: + luadata_raw = fp.read() + + try: + extract_lua(state, luadata_raw) + except Exception as E: + print(f"---\nFile: '{lua_file}'") print(E) exit(1) @@ -1216,7 +1417,7 @@ def prepare_git_file_list(): output = res.stdout.readlines() res.communicate() if res.returncode != 0: - print("'git ls-files' command exited with non-zero exit code: {}".format(res.returncode)) + print(f"'git ls-files' command exited with non-zero exit code: {res.returncode}") exit(1) for f in output: if len(f) > 0: @@ -1266,15 +1467,15 @@ def write_pot(entries, output_path, project_name): print("==> Parsing JSON") for i in sorted(directories): - print("----> Traversing directory {}".format(i)) + print(f"----> Traversing directory {i}") extract_all_from_dir(state, i) if options.warn_unused_types: print("==> Checking types") if len(known_types - found_types) != 0: - print("WARNING: type {} not found in any JSON objects".format(known_types - found_types)) + print(f"WARNING: type {known_types - found_types} not found in any JSON objects") if len(needs_plural - found_types) != 0: - print("WARNING: type {} from needs_plural not found in any JSON objects".format(needs_plural - found_types)) + print(f"WARNING: type {needs_plural - found_types} from needs_plural not found in any JSON objects") print("==> Writing POT") if not state.project_name: diff --git a/lang/po/ar.po b/lang/po/ar.po index c9d79242e189..8aeabe0187b8 100644 --- a/lang/po/ar.po +++ b/lang/po/ar.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2020 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2020\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Arabic (https://app.transifex.com/bn-team/teams/113585/ar/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1490,10 +1490,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3948,10 +3956,28 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -8090,6 +8116,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -22063,34 +22100,122 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -22099,30 +22224,107 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -22131,6 +22333,18 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -22139,6 +22353,17 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -22147,18 +22372,71 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -51184,8 +51462,8 @@ msgstr[5] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -51201,8 +51479,8 @@ msgstr[5] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -51219,8 +51497,8 @@ msgstr[5] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -53175,8 +53453,25 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" @@ -53184,13 +53479,47 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -53623,8 +53952,8 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" @@ -53632,14 +53961,14 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" @@ -53647,14 +53976,14 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" @@ -53662,14 +53991,14 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" @@ -53677,7 +54006,7 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -82127,6 +82456,66 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -83531,6 +83920,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -86738,6 +87128,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -95093,6 +95484,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -133189,16 +133581,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" -msgstr[5] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -134016,16 +134398,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" -msgstr[5] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -144539,7 +144911,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -152343,10 +152716,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -165688,6 +166057,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -165724,6 +166103,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -197636,6 +198029,17 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -208585,6 +208989,17 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -223735,6 +224150,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -223862,6 +224282,36 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -228219,6 +228669,26 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -228560,6 +229030,7 @@ msgstr[4] "" msgstr[5] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -228570,6 +229041,7 @@ msgstr[4] "" msgstr[5] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -228660,6 +229132,7 @@ msgstr[4] "" msgstr[5] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -228670,6 +229143,7 @@ msgstr[4] "" msgstr[5] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -228959,6 +229433,26 @@ msgstr[3] "" msgstr[4] "" msgstr[5] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -230083,6 +230577,126 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -231521,6 +232135,24 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -233100,6 +233732,16 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -233119,16 +233761,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" -msgstr[5] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -236482,10 +237114,30 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -239039,6 +239691,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -239061,6 +239722,82 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" +msgstr[4] "" +msgstr[5] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -240487,6 +241224,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -241042,6 +241787,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -241200,7 +241965,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -246898,6 +247687,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -251751,6 +252564,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -251867,6 +252684,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -252737,6 +253558,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -265149,6 +265974,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -271055,6 +271885,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -271315,6 +272150,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -275074,6 +275916,15 @@ msgstr[5] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -278035,16 +278886,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" -msgstr[4] "" -msgstr[5] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -280684,6 +281525,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "" @@ -281756,6 +282605,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -281830,7 +282689,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -281838,7 +282697,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -281846,7 +282705,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -281854,7 +282713,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -281862,7 +282721,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -281870,7 +282729,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -281878,7 +282737,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -281886,7 +282745,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -289503,6 +290362,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/da.po b/lang/po/da.po index d8732bf53f77..d9826276d1e7 100644 --- a/lang/po/da.po +++ b/lang/po/da.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2020 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2020\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Danish (https://app.transifex.com/bn-team/teams/113585/da/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1490,10 +1490,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3856,10 +3864,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -7998,6 +8020,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21871,34 +21904,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21907,30 +21996,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21939,6 +22077,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -21947,6 +22093,13 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -21955,18 +22108,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -47532,8 +47718,8 @@ msgstr[1] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47545,8 +47731,8 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47559,8 +47745,8 @@ msgstr[1] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49031,18 +49217,57 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -49375,45 +49600,45 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -71435,6 +71660,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -72513,6 +72782,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -74912,6 +75182,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -81223,6 +81494,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -111223,12 +111495,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -111866,12 +112132,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -122005,7 +122265,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -129809,10 +130070,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -143142,6 +143399,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -143178,6 +143445,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -172938,6 +173219,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -182823,6 +183111,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -194813,6 +195108,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -194940,6 +195240,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -198777,6 +199095,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -198982,12 +199312,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -199042,12 +199374,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -199221,6 +199555,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -200109,6 +200455,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -201183,6 +201601,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -202258,6 +202690,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -202273,12 +202711,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -205104,10 +205536,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -207429,6 +207873,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -207451,6 +207904,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -208877,6 +209402,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -209432,6 +209965,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -209590,7 +210143,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -215132,6 +215709,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -219933,6 +220534,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -220049,6 +220654,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -220915,6 +221524,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -233211,6 +233824,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -239069,6 +239687,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -239329,6 +239952,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -243040,6 +243670,15 @@ msgstr[1] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -245997,12 +246636,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -248598,6 +249231,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Generel" @@ -249678,6 +250319,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -249752,7 +250403,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -249760,7 +250411,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -249768,7 +250419,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -249776,7 +250427,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -249784,7 +250435,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -249792,7 +250443,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -249800,7 +250451,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -249808,7 +250459,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -257357,6 +258008,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/de.po b/lang/po/de.po index e04e0f9907bf..296dcd7e044b 100644 --- a/lang/po/de.po +++ b/lang/po/de.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Coolthulhu , 2023\n" "Language-Team: German (https://app.transifex.com/bn-team/teams/113585/de/)\n" "MIME-Version: 1.0\n" @@ -1611,10 +1611,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4186,10 +4194,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "Blinddarm" @@ -8567,6 +8589,17 @@ msgstr "" msgid "You're winded." msgstr "Du bist erschöpft." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "Die Decke bricht auf dich herab!" @@ -23515,34 +23548,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -23551,30 +23640,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "ein Fungus" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "ein Insekt" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -23583,6 +23721,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "Zombie" +msgstr[1] "Zombies" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "ein Zombie" @@ -23591,6 +23737,13 @@ msgstr "ein Zombie" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -23599,18 +23752,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "eine Anomalie" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "Mensch" +msgstr[1] "Menschen" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -50700,12 +50886,9 @@ msgstr[1] "20x66mm-Flechet, selbstgemacht" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Selbstgemachte, illegale Duplikate von Rivtechs hülsenlosen 20×66mm " -"Flechetpatronen. Weil sie hülsenlos sind, können diese Patronen weder " -"demontiert noch wiedergeladen werden." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -50716,12 +50899,9 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Selbstgemachte, illegale Duplikate von Rivtechs hülsenlosen 20×66mm-Posten. " -"Weil sie hülsenlos sind, können diese Patronen weder demontiert noch " -"wiedergeladen werden." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -50733,12 +50913,9 @@ msgstr[1] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Selbstgemachte, illegale Duplikate von Rivtechs hülsenlosen 20×66mm-" -"Massivpatronen. Weil sie hülsenlos sind, können diese Patronen weder " -"demontiert noch wiedergeladen werden." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -52487,20 +52664,56 @@ msgstr "" "Truppenbewegungen." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"Selbstgemachte, illegale Duplikate von Rivtechs hülsenlosen 8×40mm-Patronen." -" Weil sie hülsenlos sind, können diese Patronen weder demontiert noch " -"wiedergeladen werden." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -52905,45 +53118,45 @@ msgstr "" "Ein Rohr mit kleinen Paintballs. Sie richten praktisch keinen Schaden an." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "93mm-Einstufen-Hochexplosiv-Munition für die RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "64mm/105mm Hochexplosive - Tandemmunition für den RPG-7." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "105mm thermobarische Munition für den RPG-7." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -76784,6 +76997,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "Ein Solei. Recht salzig, aber schmeckt gut und ist lange haltbar." +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -78001,6 +78258,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -80591,6 +80849,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "Kaugummi" @@ -87432,6 +87691,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -117171,8 +117431,8 @@ msgstr "" msgctxt "fish" msgid "pike" msgid_plural "pikes" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "Pike" +msgstr[1] "Piken" #. ~ Description for {'ctxt': 'fish', 'str': 'pike'} #: data/json/monsters/fish.json @@ -120560,12 +120820,6 @@ msgstr "" "färbte sich blassgelb vom Leben unter der Erde. Sie schwärmt unter dem Boden" " aus und ist nach ihrer Gewohnheit, Abwässerkanäle zu verseuchen, benannt." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -121294,12 +121548,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "Zombie" -msgstr[1] "Zombies" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -132372,7 +132620,8 @@ msgid "I'll kill you if you don't." msgstr "Wenn du es nicht tust, werd ich dich töten." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "Vergiss es." @@ -140770,10 +141019,6 @@ msgstr "Monster" msgid "demon" msgstr "Dämon" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "Schrecken" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "unbeschreibliche Bestie" @@ -155367,6 +155612,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -155403,6 +155658,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -187445,6 +187714,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -197433,6 +197709,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -209530,6 +209813,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -209657,6 +209945,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -213494,6 +213800,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -213699,12 +214017,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -213759,12 +214079,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -213938,6 +214260,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -214826,6 +215160,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -215902,6 +216308,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -216977,6 +217397,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -216992,12 +217418,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -220045,10 +220465,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -222498,6 +222930,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -222520,6 +222961,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -224054,6 +224567,14 @@ msgstr "Debugmodus umschalten" msgid "Debug Menu" msgstr "Debugmenü" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Duftnotenvisualisierung ein/aus" @@ -224609,6 +225130,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -224767,7 +225308,31 @@ msgstr "Turmzielmodus anpassen" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -230463,6 +231028,30 @@ msgstr "abcdefghijklmnopqrstuvwxyzäöüß" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -235347,6 +235936,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -235463,6 +236056,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -236332,6 +236929,10 @@ msgstr "Dort ist kein Fahrzeug." msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -248977,6 +249578,11 @@ msgstr "%s wirft es dir aus deiner Hand!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "Du versuchst, %s mit etwas %s zu füttern, aber es verschwindet!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -254967,6 +255573,11 @@ msgstr "" msgid "Create World" msgstr "Welt erstellen" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "Bugs? Vorschläge? Verwende die Links unter MOTD, um sie zu melden. " @@ -255227,6 +255838,13 @@ msgstr "Willst du %s wirklich löschen?" msgid "Sorry, something went wrong." msgstr "Tschuldigung, etwas ging schief." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -258986,6 +259604,15 @@ msgstr[1] "" msgid "Mod version" msgstr "Mod-Version" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -262029,12 +262656,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "Mensch" -msgstr[1] "Menschen" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -264693,6 +265314,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Allgemein" @@ -265853,6 +266482,16 @@ msgstr "Animationsverzögerung" msgid "The amount of time to pause between animation frames in ms." msgstr "Die Zeit in ms, welche zwischen Animationseinzelbildern vergeht." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -265927,7 +266566,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -265935,7 +266574,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -265943,7 +266582,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -265951,7 +266590,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -265959,7 +266598,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -265967,7 +266606,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -265975,7 +266614,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -265983,7 +266622,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -273794,6 +274433,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "(entfällt)" diff --git a/lang/po/el.po b/lang/po/el.po index 790a93827371..0fb4a544c06e 100644 --- a/lang/po/el.po +++ b/lang/po/el.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2020 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2020\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Greek (https://app.transifex.com/bn-team/teams/113585/el/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1490,10 +1490,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3856,10 +3864,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -7998,6 +8020,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21880,34 +21913,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21916,30 +22005,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21948,6 +22086,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -21956,6 +22102,13 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -21964,18 +22117,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -47566,11 +47752,9 @@ msgstr[1] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Χειροποίητα λαθραίο αντίγραφα του Rivtech 20x66mm χωρίς κασετίνα τύπου " -"flechette. Οι σφαίρες δεν μπορούν να αποσυναρμολογηθούν ή να οπλιστούν ξανά." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -47581,11 +47765,9 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Χειροποίητα λαθραίο αντίγραφα του Rivtech 8x40mm χωρίς κασετίνα τύπου " -"buckshot. Οι σφαίρες δεν μπορούν να αποσυναρμολογηθούν ή να οπλιστούν ξανά." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -47597,11 +47779,9 @@ msgstr[1] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Χειροποίητα λαθραία αντίγραφα του Rivtech 20x66mm χωρίς κασετίνα βλήματα. Τα" -" βλήματα δεν μπορούν να αποσυναρμολογηθούν ή να οπλιστούν ξανά." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -49113,18 +49293,57 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -49468,45 +49687,45 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "93mm μονής φάσης, υψηλής εκρηκτικής δύναμης πυρομαχικά για το RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -71897,6 +72116,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -72973,6 +73236,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -75372,6 +75636,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -81685,6 +81950,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -111702,12 +111968,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -112345,12 +112605,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -122484,7 +122738,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -130288,10 +130543,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -143621,6 +143872,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -143657,6 +143918,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -173434,6 +173709,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -183319,6 +183601,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -195309,6 +195598,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -195436,6 +195730,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -199273,6 +199585,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -199478,12 +199802,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -199538,12 +199864,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -199717,6 +200045,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -200605,6 +200945,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -201679,6 +202091,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -202754,6 +203180,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -202769,12 +203201,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -205600,10 +206026,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -207925,6 +208363,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -207947,6 +208394,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -209373,6 +209892,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -209928,6 +210455,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -210086,7 +210633,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -215628,6 +216199,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -220429,6 +221024,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -220545,6 +221144,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -221411,6 +222014,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -233707,6 +234314,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -239565,6 +240177,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -239825,6 +240442,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -243536,6 +244160,15 @@ msgstr[1] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -246493,12 +247126,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -249094,6 +249721,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Γενικές" @@ -250193,6 +250828,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -250267,7 +250912,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -250275,7 +250920,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -250283,7 +250928,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -250291,7 +250936,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -250299,7 +250944,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -250307,7 +250952,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -250315,7 +250960,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -250323,7 +250968,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -257872,6 +258517,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/es_AR.po b/lang/po/es_AR.po index 9724a32815f5..a86a0f55df2f 100644 --- a/lang/po/es_AR.po +++ b/lang/po/es_AR.po @@ -1,12 +1,12 @@ # # Translators: -# Jean Germain , 2020 +# Jean Germain , 2023 # Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Coolthulhu , 2023\n" "Language-Team: Spanish (Argentina) (https://app.transifex.com/bn-team/teams/113585/es_AR/)\n" "MIME-Version: 1.0\n" @@ -2237,10 +2237,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4821,10 +4829,25 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "apéndice" @@ -9160,6 +9183,17 @@ msgstr "" msgid "You're winded." msgstr "Te falta el aire." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "¡El techo se te cae encima!" @@ -10141,9 +10175,9 @@ msgstr "" #: data/json/field_type.json data/json/monsters/nether.json msgid "shadow" msgid_plural "shadows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sombra" +msgstr[1] "sombras" +msgstr[2] "sombras" #: data/json/field_type.json msgid "sparks" @@ -24306,34 +24340,98 @@ msgstr[0] "si ves esto es un bug" msgstr[1] "si ves esto es un bug" msgstr[2] "si ves esto es un bug" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "masa" +msgstr[1] "masas" +msgstr[2] "masas" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -24342,30 +24440,86 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "un hongo" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "un insecto" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -24374,6 +24528,15 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "zombi" +msgstr[1] "zombis" +msgstr[2] "zombis" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "un zombi" @@ -24382,6 +24545,14 @@ msgstr "un zombi" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -24390,18 +24561,56 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "una aberración" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "humano" +msgstr[1] "humanos" +msgstr[2] "humanos" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -36365,9 +36574,9 @@ msgstr "" #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal wall" msgid_plural "fungal walls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pared fúngica" +msgstr[1] "paredes fúngicas" +msgstr[2] "paredes fúngicas" #. ~ Description for fungal wall #: data/json/furniture_and_terrain/terrain-fungal.json @@ -41068,9 +41277,9 @@ msgstr "" #: data/json/items/battery.json msgid "ultra-light battery" msgid_plural "ultra-light batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "batería ultraligera" +msgstr[1] "baterías ultraligeras" +msgstr[2] "baterías ultraligeras" #. ~ Description for {'str': 'ultra-light battery', 'str_pl': 'ultra-light #. batteries'} @@ -41102,9 +41311,9 @@ msgstr "" #: data/json/items/battery.json msgid "ultra-light disposable battery" msgid_plural "ultra-light disposable batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "batería desechable ultraligera" +msgstr[1] "baterías desechables ultraligeras" +msgstr[2] "baterías desechables ultraligeras" #. ~ Description for {'str': 'ultra-light disposable battery', 'str_pl': #. 'ultra-light disposable batteries'} @@ -41122,9 +41331,9 @@ msgstr "" #: data/json/items/battery.json msgid "light battery" msgid_plural "light batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "batería ligera" +msgstr[1] "baterías ligeras" +msgstr[2] "baterías ligeras" #. ~ Description for {'str': 'light battery', 'str_pl': 'light batteries'} #: data/json/items/battery.json @@ -41138,9 +41347,9 @@ msgstr "" #: data/json/items/battery.json msgid "light battery (high-capacity)" msgid_plural "light batteries (high-capacity)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "batería ligera (alta capacidad)" +msgstr[1] "baterías ligeras (alta capacidad)" +msgstr[2] "baterías ligeras (alta capacidad)" #. ~ Description for {'str': 'light battery (high-capacity)', 'str_pl': 'light #. batteries (high-capacity)'} @@ -41172,9 +41381,9 @@ msgstr "" #: data/json/items/battery.json msgid "light disposable battery" msgid_plural "light disposable batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "batería desechable ligera" +msgstr[1] "baterías desechables ligeras" +msgstr[2] "baterías desechables ligeras" #. ~ Description for {'str': 'light disposable battery', 'str_pl': 'light #. disposable batteries'} @@ -52257,9 +52466,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "electric guitar" msgid_plural "electric guitars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guitarra eléctrica" +msgstr[1] "guitarras eléctricas" +msgstr[2] "guitarras eléctricas" #. ~ Description for {'str': 'electric guitar'} #: data/json/items/tool_armor.json @@ -52685,9 +52894,9 @@ msgstr "" #: data/json/items/toolmod.json msgid "light battery mod" msgid_plural "light battery mods" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "modificador de batería ligera" +msgstr[1] "modificadores de baterías ligeras" +msgstr[2] "modificadores de baterías ligeras" #. ~ Description for {'str': 'light battery mod'} #: data/json/items/toolmod.json @@ -52794,12 +53003,9 @@ msgstr[2] "20x66mm dardos perforantes, casera" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Son réplicas truchas de las balas de Rivtech 20x66mm sin casquillo, con una " -"carga de dardos perforantes. Al no tener casquillo, no pueden ser desarmadas" -" ni recargadas." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -52811,11 +53017,9 @@ msgstr[2] "perdigones grandes 20x66mm, casero" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Son réplicas truchas de las balas de Rivtech 20x66mm sin casquillo. Al no " -"tener casquillo, no pueden ser desarmadas ni recargadas." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -52828,12 +53032,9 @@ msgstr[2] "postas 20x66mm, casera" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Son réplicas truchas de las balas de Rivtech 20x66mm sin casquillo, de " -"proyectil sólido. Al no tener casquillo, no pueden ser desarmadas ni " -"recargadas." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -54682,20 +54883,60 @@ msgstr "" "los movimientos de las tropas." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" -msgstr[0] "8x40mm JHP trucho" -msgstr[1] "8x40mm JHP truchos" -msgstr[2] "8x40mm JHP truchos" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"Son unas réplicas truchas de las balas 8x40mm sin casquillo de Rivtech. Al " -"no tener casquillo, no pueden ser desarmadas ni recargadas." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -55119,49 +55360,49 @@ msgstr "" " daño." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" -msgstr[0] "misil PG-7VL 93mm" -msgstr[1] "misiles PG-7VL 93mm" -msgstr[2] "misiles PG-7VL 93mm" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Es munición 93mm monoetapa de alta explosividad para el RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" -msgstr[0] "misil PG-7VR 64mm/105mm" -msgstr[1] "misiles PG-7VR 64mm/105mm" -msgstr[2] "misiles PG-7VR 64mm/105mm" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "Es munición 64mm/105mm de alta explosividad para el RPG-7." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" -msgstr[0] "misil TBG-7V 105mm" -msgstr[1] "misiles TBG-7V 105mm" -msgstr[2] "misiles TBG-7V 105mm" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "Es munición termobárica 105mm para el RPG-7." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" -msgstr[0] "misil OG-7V 40mm" -msgstr[1] "misiles OG-7V 40mm" -msgstr[2] "misiles OG-7V 40mm" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -81800,6 +82041,54 @@ msgstr "" "Es huevo al escabeche. Bastante salado, pero tiene buen sabor y dura mucho " "tiempo." +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -83086,6 +83375,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "masita" @@ -85889,6 +86179,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "chicle" @@ -93398,6 +93689,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "galletita" @@ -94105,9 +94397,9 @@ msgstr "" #: data/json/items/corpses/inactive_bots.json msgid "inactive prototype cyborg" msgid_plural "inactive prototype cyborgs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "prototipo de ciborg inactivo" +msgstr[1] "prototipos de ciborg inactivos" +msgstr[2] "prototipos de ciborg inactivos" #. ~ Use action friendly_msg for {'str': 'inactive prototype cyborg'}. #: data/json/items/corpses/inactive_bots.json @@ -94784,9 +95076,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid "unused .22 casing" msgid_plural "unused .22 casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo nuevo .22" +msgstr[1] "casquillos nuevos .22" +msgstr[2] "casquillos nuevos .22" #. ~ Description for {'str': 'unused .22 casing'} #: data/json/items/generic/casing.json @@ -94810,9 +95102,9 @@ msgstr "Es una vaina servida de una bala calibre .30-06." #: data/json/items/generic/casing.json msgid ".270 Winchester casing" msgid_plural ".270 Winchester casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo .270 Winchester" +msgstr[1] "casquillos .270 Winchester" +msgstr[2] "casquillos .270 Winchester" #. ~ Description for {'str': '.270 Winchester casing'} #: data/json/items/generic/casing.json @@ -94882,9 +95174,9 @@ msgstr "Es una vaina servida de una bala calibre .38 Special." #: data/json/items/generic/casing.json msgid ".38 Super casing" msgid_plural ".38 Super casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo .38 Super" +msgstr[1] "casquillos .38 Super" +msgstr[2] "casquillos .38 Super" #. ~ Description for {'str': '.38 Super casing'} #: data/json/items/generic/casing.json @@ -94906,9 +95198,9 @@ msgstr "Es una vaina servida de una bala calibre .40 S&W." #: data/json/items/generic/casing.json msgid "10mm Auto casing" msgid_plural "10mm Auto casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo 10mm Auto" +msgstr[1] "casquillos 10mm Auto" +msgstr[2] "casquillos 10mm Auto" #. ~ Description for {'str': '10mm Auto casing'} #: data/json/items/generic/casing.json @@ -94918,9 +95210,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid "40x46mm M212 casing" msgid_plural "40x46mm M212 casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo 40x46mm M212" +msgstr[1] "casquillos 40x46mm M212" +msgstr[2] "casquillos 40x46mm M212" #. ~ Description for {'str': '40x46mm M212 casing'} #: data/json/items/generic/casing.json @@ -94933,9 +95225,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid "40x46mm M118 casing" msgid_plural "40x46mm M118 casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo 40x46mm M118" +msgstr[1] "casquillos 40x46mm M118" +msgstr[2] "casquillos 40x46mm M118" #. ~ Description for {'str': '40x46mm M118 casing'} #: data/json/items/generic/casing.json @@ -94947,9 +95239,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid "40x46mm M199 casing" msgid_plural "40x46mm M199 casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo 40x46mm M199" +msgstr[1] "casquillos 40x46mm M199" +msgstr[2] "casquillos 40x46mm M199" #. ~ Description for {'str': '40x46mm M199 casing'} #: data/json/items/generic/casing.json @@ -94961,9 +95253,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid "40x46mm M195 casing" msgid_plural "40x46mm M195 casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo 40x46mm M195" +msgstr[1] "casquillos 40x46mm M195" +msgstr[2] "casquillos 40x46mm M195" #. ~ Description for {'str': '40x46mm M195 casing'} #: data/json/items/generic/casing.json @@ -94976,9 +95268,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid "40x53mm M169 casing" msgid_plural "40x53mm M169 casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo 40x53mm M169" +msgstr[1] "casquillos 40x53mm M169" +msgstr[2] "casquillos 40x53mm M169" #. ~ Description for {'str': '40x53mm M169 casing'} #: data/json/items/generic/casing.json @@ -95024,9 +95316,9 @@ msgstr "Es una vaina servida de una bala calibre .45 ACP." #: data/json/items/generic/casing.json msgid ".45 Colt casing" msgid_plural ".45 Colt casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo .45 Colt" +msgstr[1] "casquillos .45 Colt" +msgstr[2] "casquillos .45 Colt" #. ~ Description for {'str': '.45 Colt casing'} #: data/json/items/generic/casing.json @@ -95036,9 +95328,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid ".45-70 casing" msgid_plural ".45-70 casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo .45-70" +msgstr[1] "casquillos .45-70" +msgstr[2] "casquillos .45-70" #. ~ Description for {'str': '.45-70 casing'} #: data/json/items/generic/casing.json @@ -95060,9 +95352,9 @@ msgstr "Es una vaina servida de una bala calibre 4.6x30mm." #: data/json/items/generic/casing.json msgid ".460 Rowland casing" msgid_plural ".460 Rowland casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo .460 Rowland" +msgstr[1] "casquillos .460 Rowland" +msgstr[2] "casquillos .460 Rowland" #. ~ Description for {'str': '.460 Rowland casing'} #: data/json/items/generic/casing.json @@ -95216,9 +95508,9 @@ msgstr "Es una vaina servida de una bala calibre .357 SIG." #: data/json/items/generic/casing.json msgid ".357 magnum casing" msgid_plural ".357 magnum casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo magnum .357" +msgstr[1] "casquillos magnum .357" +msgstr[2] "casquillos magnum .357" #. ~ Description for {'str': '.357 magnum casing'} #: data/json/items/generic/casing.json @@ -95240,9 +95532,9 @@ msgstr "Es una vaina servida de una bala calibre 9x18mm." #: data/json/items/generic/casing.json msgid ".380 ACP casing" msgid_plural ".380 ACP casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo .380 ACP" +msgstr[1] "casquillos .380 ACP" +msgstr[2] "casquillos .380 ACP" #. ~ Description for {'str': '.380 ACP casing'} #: data/json/items/generic/casing.json @@ -95290,9 +95582,9 @@ msgstr "" #: data/json/items/generic/casing.json msgid ".300BLK casing" msgid_plural ".300BLK casings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casquillo .300BLK" +msgstr[1] "casquillos .300BLK" +msgstr[2] "casquillos .300BLK" #. ~ Description for {'str': '.300BLK casing'} #: data/json/items/generic/casing.json @@ -95541,9 +95833,9 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "tin cup" msgid_plural "tin cups" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "taza de lata" +msgstr[1] "tazas de lata" +msgstr[2] "tazas de lata" #. ~ Description for {'str': 'tin cup'} #: data/json/items/generic/dining_kitchen.json @@ -95569,9 +95861,9 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "drinking glass" msgid_plural "drinking glasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vaso" +msgstr[1] "vasos" +msgstr[2] "vasos" #. ~ Description for {'str': 'drinking glass', 'str_pl': 'drinking glasses'} #: data/json/items/generic/dining_kitchen.json @@ -95812,9 +96104,9 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "cast-iron frying pan" msgid_plural "cast-iron frying pans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sartén de hierro fundido" +msgstr[1] "sartenes de hierro fundido" +msgstr[2] "sartenes de hierro fundido" #. ~ Description for {'str': 'cast-iron frying pan'} #: data/json/items/generic/dining_kitchen.json @@ -95827,9 +96119,9 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "steel frying pan" msgid_plural "steel frying pans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sartén de acero" +msgstr[1] "sartenes de acero" +msgstr[2] "sartenes de acero" #. ~ Description for {'str': 'steel frying pan'} #: data/json/items/generic/dining_kitchen.json @@ -95842,9 +96134,9 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "copper frying pan" msgid_plural "copper frying pans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sartén de cobre" +msgstr[1] "sartenes de cobre" +msgstr[2] "sartenes de cobre" #. ~ Description for {'str': 'copper frying pan'} #: data/json/items/generic/dining_kitchen.json @@ -96227,9 +96519,9 @@ msgstr "" #: data/json/items/generic/string.json msgid "short string" msgid_plural "short strings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cuerda corta" +msgstr[1] "cuerdas cortas" +msgstr[2] "cuerdas cortas" #. ~ Description for {'str': 'short string'} #: data/json/items/generic/string.json @@ -102262,9 +102554,9 @@ msgstr "" #: data/json/items/magazine/12mm.json msgid "H&K G80 magazine" msgid_plural "H&K G80 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cargador H&K G80" +msgstr[1] "Cargadores H&K G80" +msgstr[2] "Cargadores H&K G80" #. ~ Description for {'str': 'H&K G80 magazine'} #: data/json/items/magazine/12mm.json @@ -102402,9 +102694,9 @@ msgstr "" #: data/json/items/magazine/22.json msgid "S&W 22A magazine" msgid_plural "S&W 22A magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador S&W 22A" +msgstr[1] "cargadores S&W 22A" +msgstr[2] "cargadores S&W 22A" #. ~ Description for {'str': 'S&W 22A magazine'} #: data/json/items/magazine/22.json @@ -103443,9 +103735,9 @@ msgstr "" #: data/json/items/magazine/40.json msgid "Glock 22 magazine" msgid_plural "Glock 22 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador Glock 22" +msgstr[1] "cargadores Glock 22" +msgstr[2] "cargadores Glock 22" #. ~ Description for {'str': 'Glock 22 magazine'} #: data/json/items/magazine/40.json @@ -103457,9 +103749,9 @@ msgstr "" #: data/json/items/magazine/40.json msgid "Px4 .40 magazine" msgid_plural "Px4 .40 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador Px4 .40" +msgstr[1] "cargadores Px4 .40" +msgstr[2] "cargadores Px4 .40" #. ~ Description for {'str': 'Px4 .40 magazine'} #: data/json/items/magazine/40.json @@ -103470,9 +103762,9 @@ msgstr "" #: data/json/items/magazine/40.json msgid "SIG Pro .40 magazine" msgid_plural "SIG Pro .40 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador SIG Pro .40" +msgstr[1] "cargadores SIG Pro .40" +msgstr[2] "cargadores SIG Pro .40" #. ~ Description for {'str': 'SIG Pro .40 magazine'} #: data/json/items/magazine/40.json @@ -103559,9 +103851,9 @@ msgstr "" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "grenade belt" msgid_plural "grenade belts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón de granadas" +msgstr[1] "cinturones de granadas" +msgstr[2] "cinturones de granadas" #. ~ Description for {'str': 'grenade belt'} #: data/json/items/magazine/40mm.json @@ -103634,9 +103926,9 @@ msgstr "" #: data/json/items/magazine/45.json msgid "MAC-10 magazine" msgid_plural "MAC-10 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador MAC-10" +msgstr[1] "cargadores MAC-10" +msgstr[2] "cargadores MAC-10" #. ~ Description for {'str': 'MAC-10 magazine'} #: data/json/items/magazine/45.json @@ -103733,9 +104025,9 @@ msgstr "" #: data/json/items/magazine/45.json msgid "UMP45 magazine" msgid_plural "UMP45 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador UMP45" +msgstr[1] "cargadores UMP45" +msgstr[2] "cargadores UMP45" #. ~ Description for {'str': 'UMP45 magazine'} #: data/json/items/magazine/45.json @@ -103760,9 +104052,9 @@ msgstr "" #: data/json/items/magazine/45.json msgid "USP .45 magazine" msgid_plural "USP .45 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador USP .45" +msgstr[1] "cargadores USP .45" +msgstr[2] "cargadores USP .45" #. ~ Description for {'str': 'USP .45 magazine'} #: data/json/items/magazine/45.json @@ -103859,9 +104151,9 @@ msgstr "" #: data/json/items/magazine/46.json msgid "H&K 4.6mm magazine" msgid_plural "H&K 4.6mm magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador H&K 4.6mm" +msgstr[1] "cargadores H&K 4.6mm" +msgstr[2] "cargadores H&K 4.6mm" #. ~ Description for {'str': 'H&K 4.6mm magazine'} #: data/json/items/magazine/46.json @@ -103875,9 +104167,9 @@ msgstr "" #: data/json/items/magazine/460.json msgid "M1911 extended magazine" msgid_plural "M1911 extended magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador M1911 extendido" +msgstr[1] "cargadores M1911 extendido" +msgstr[2] "cargadores M1911 extendido" #. ~ Description for {'str': 'M1911 extended magazine'} #: data/json/items/magazine/460.json @@ -103887,9 +104179,9 @@ msgstr "Es un cargador extendido de 10 balas para usar en la pistola M1911." #: data/json/items/magazine/460.json msgid "M1911 magazine" msgid_plural "M1911 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador M1911" +msgstr[1] "cargadores M1911" +msgstr[2] "cargadores M1911" #. ~ Description for {'str': 'M1911 magazine'} #: data/json/items/magazine/460.json @@ -103921,9 +104213,9 @@ msgstr "" #: data/json/items/magazine/50.json msgid "AS50 magazine" msgid_plural "AS50 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador AS50" +msgstr[1] "cargadores AS50" +msgstr[2] "cargadores AS50" #. ~ Description for {'str': 'AS50 magazine'} #: data/json/items/magazine/50.json @@ -103933,9 +104225,9 @@ msgstr "" #: data/json/items/magazine/50.json msgid "TAC-50 magazine" msgid_plural "TAC-50 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador TAC-50" +msgstr[1] "cargadores TAC-50" +msgstr[2] "cargadores TAC-50" #. ~ Description for {'str': 'TAC-50 magazine'} #: data/json/items/magazine/50.json @@ -103959,9 +104251,9 @@ msgstr "" #: data/json/items/magazine/545x39.json msgid "AK-74M magazine" msgid_plural "AK-74M magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador AK-74M" +msgstr[1] "cargadores AK-74M" +msgstr[2] "cargadores AK-74M" #. ~ Description for {'str': 'AK-74M magazine'} #: data/json/items/magazine/545x39.json @@ -103991,9 +104283,9 @@ msgstr "" #: data/json/items/magazine/57.json msgid "FN-57 magazine" msgid_plural "FN-57 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador FN-57" +msgstr[1] "cargadores FN-57" +msgstr[2] "cargadores FN-57" #. ~ Description for {'str': 'FN-57 magazine'} #: data/json/items/magazine/57.json @@ -104003,9 +104295,9 @@ msgstr "Es un cargador de capacidad estándar para usar en el FN Five-Seven." #: data/json/items/magazine/57.json msgid "FN-P90 magazine" msgid_plural "FN-P90 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador FN-P90" +msgstr[1] "cargadores FN-P90" +msgstr[2] "cargadores FN-P90" #. ~ Description for {'str': 'FN-P90 magazine'} #: data/json/items/magazine/57.json @@ -104180,9 +104472,9 @@ msgstr "Es un cargador estándar de 8 balas para la Tokarev TT-33." #: data/json/items/magazine/8x40mm.json msgid "RMGB100 8x40mm magazine" msgid_plural "RMGB100 8x40mm magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador RMGB100 8x40mm" +msgstr[1] "cargadores RMGB100 8x40mm" +msgstr[2] "cargadores RMGB100 8x40mm" #. ~ Description for {'str': 'RMGB100 8x40mm magazine'} #: data/json/items/magazine/8x40mm.json @@ -104315,9 +104607,9 @@ msgstr "" #: data/json/items/magazine/9mm.json msgid "Glock magazine" msgid_plural "Glock magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador Glock" +msgstr[1] "cargadores Glock" +msgstr[2] "cargadores Glock" #. ~ Description for {'str': 'Glock magazine'} #: data/json/items/magazine/9mm.json @@ -104427,9 +104719,9 @@ msgstr "" #: data/json/items/magazine/9mm.json msgid "MP5 magazine" msgid_plural "MP5 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador MP5" +msgstr[1] "cargadores MP5" +msgstr[2] "cargadores MP5" #. ~ Description for {'str': 'MP5 magazine'} #: data/json/items/magazine/9mm.json @@ -104514,9 +104806,9 @@ msgstr "" #: data/json/items/magazine/9mm.json msgid "UZI magazine" msgid_plural "UZI magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador UZI" +msgstr[1] "cargadores UZI" +msgstr[2] "cargadores UZI" #. ~ Description for {'str': 'UZI magazine'} #: data/json/items/magazine/9mm.json @@ -104696,9 +104988,9 @@ msgstr "" #: data/json/items/magazine/9mm.json msgid "CCP magazine" msgid_plural "CCP magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador CCP" +msgstr[1] "cargadores CCP" +msgstr[2] "cargadores CCP" #. ~ Description for {'str': 'CCP magazine'} #: data/json/items/magazine/9mm.json @@ -106600,9 +106892,9 @@ msgstr "" msgctxt "weapon" msgid "pike" msgid_plural "pikes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lucio" +msgstr[1] "lucios" +msgstr[2] "lucios" #. ~ Description for {'ctxt': 'weapon', 'str': 'pike'} #: data/json/items/melee/spears_and_polearms.json @@ -109164,9 +109456,9 @@ msgstr "" msgctxt "weapon" msgid "sling" msgid_plural "slings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "honda" +msgstr[1] "hondas" +msgstr[2] "hondas" #: data/json/items/ranged/slings.json msgid "" @@ -109373,9 +109665,9 @@ msgstr "" #: data/json/items/ranged/throwing.json msgid "frisbee" msgid_plural "frisbees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "frisbee" +msgstr[1] "frisbees" +msgstr[2] "frisbees" #. ~ Description for {'str': 'frisbee'} #: data/json/items/ranged/throwing.json @@ -109401,9 +109693,9 @@ msgstr "" #: data/json/items/ranged/throwing.json msgid "lawn dart" msgid_plural "lawn darts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dardo de plástico" +msgstr[1] "dardos de plástico" +msgstr[2] "dardos de plástico" #. ~ Description for {'str': 'lawn dart'} #: data/json/items/ranged/throwing.json @@ -109413,9 +109705,9 @@ msgstr "Un dardo largo de plástico para deportes al aire libre." #: data/json/items/ranged/throwing.json msgid "throwing axe" msgid_plural "throwing axes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hacha arrojadiza" +msgstr[1] "hachas arrojadizas" +msgstr[2] "hachas arrojadizas" #. ~ Description for {'str': 'throwing axe'} #: data/json/items/ranged/throwing.json @@ -110798,9 +111090,9 @@ msgstr "" #: data/json/items/resources/wood.json src/crafting_gui.cpp msgid "plank" msgid_plural "planks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tablón" +msgstr[1] "tablones" +msgstr[2] "tablones" #. ~ Description for {'str': 'plank'} #: data/json/items/resources/wood.json @@ -117473,9 +117765,9 @@ msgstr "" #: data/json/items/tool/toiletries.json msgid "scrub brush" msgid_plural "scrub brushes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cepillo de fregar" +msgstr[1] "cepillos de fregar" +msgstr[2] "cepillos de fregar" #. ~ Description for {'str': 'scrub brush', 'str_pl': 'scrub brushes'} #: data/json/items/tool/toiletries.json @@ -117564,9 +117856,9 @@ msgstr "" #: data/json/items/tool/toiletries.json msgid "sponge" msgid_plural "sponges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esponja" +msgstr[1] "esponjas" +msgstr[2] "esponjas" #. ~ Description for {'str': 'sponge'} #: data/json/items/tool/toiletries.json @@ -118506,9 +118798,9 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "misc repair kit" msgid_plural "misc repair kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "kit de reparación misceláneo" +msgstr[1] "kits de reparación misceláneos" +msgstr[2] "kits de reparación misceláneos" #. ~ Description for {'str': 'misc repair kit'} #: data/json/items/tool/workshop.json @@ -118769,9 +119061,9 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "extended toolset" msgid_plural "extended toolsets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "conjunto de herramientas extendida" +msgstr[1] "conjuntos de herramientas extendidas" +msgstr[2] "conjuntos de herramientas extendidas" #. ~ Description for {'str': 'extended toolset'} #: data/json/items/tool/workshop.json @@ -118783,9 +119075,9 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "arc welder" msgid_plural "arc welders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "soldador de arco" +msgstr[1] "soldadores de arco" +msgstr[2] "soldadores de arco" #. ~ Description for {'str': 'arc welder'} #: data/json/items/tool/workshop.json @@ -118797,9 +119089,9 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "makeshift arc welder" msgid_plural "makeshift arc welders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "soldador de arco improvisado" +msgstr[1] "soldadores de arco improvisados" +msgstr[2] "soldadores de arco improvisados" #. ~ Description for {'str': 'makeshift arc welder'} #: data/json/items/tool/workshop.json @@ -121464,9 +121756,9 @@ msgstr "" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "wheel" msgid_plural "wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda" +msgstr[1] "ruedas" +msgstr[2] "ruedas" #. ~ Description for {'str': 'wheel'} #: data/json/items/vehicle/wheel.json @@ -121492,9 +121784,9 @@ msgstr "" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "armored wheel" msgid_plural "armored wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda blindada" +msgstr[1] "ruedas blindadas" +msgstr[2] "ruedas blindadas" #. ~ Description for {'str': 'armored wheel'} #: data/json/items/vehicle/wheel.json @@ -121516,9 +121808,9 @@ msgstr "Una rueda chica como la de una carretilla normal de jardinería." #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "bicycle wheel" msgid_plural "bicycle wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda de bicicleta" +msgstr[1] "ruedas de bicicleta" +msgstr[2] "ruedas de bicicleta" #. ~ Description for {'str': 'bicycle wheel'} #: data/json/items/vehicle/wheel.json @@ -121566,9 +121858,9 @@ msgstr "" #: data/json/items/vehicle/wheel.json data/json/obsoletion/uncategorized.json msgid "metal wheel" msgid_plural "metal wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda de metal" +msgstr[1] "ruedas de metal" +msgstr[2] "ruedas de metal" #. ~ Description for {'str': 'metal wheel'} #: data/json/items/vehicle/wheel.json @@ -121607,9 +121899,9 @@ msgstr "" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "motorbike wheel" msgid_plural "motorbike wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda de moto" +msgstr[1] "ruedas de moto" +msgstr[2] "ruedas de moto" #. ~ Description for {'str': 'motorbike wheel'} #: data/json/items/vehicle/wheel.json @@ -121633,9 +121925,9 @@ msgstr "" #: data/json/items/vehicle/wheel.json msgid "large steel drum" msgid_plural "large steel drums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tambor grande de acero" +msgstr[1] "tambores grande de acero" +msgstr[2] "tambores grande de acero" #. ~ Description for {'str': 'large steel drum'} #: data/json/items/vehicle/wheel.json @@ -121653,9 +121945,9 @@ msgstr "" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "small wheel" msgid_plural "small wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda pequeña" +msgstr[1] "ruedas pequeñas" +msgstr[2] "ruedas pequeñas" #. ~ Description for {'str': 'small wheel'} #: data/json/items/vehicle/wheel.json @@ -121697,9 +121989,9 @@ msgstr "Un par de ruedas de una silla de ruedas." #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "wide wheel" msgid_plural "wide wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda ancha" +msgstr[1] "ruedas anchas" +msgstr[2] "ruedas anchas" #. ~ Description for {'str': 'wide wheel'} #: data/json/items/vehicle/wheel.json @@ -121725,9 +122017,9 @@ msgstr "" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "wooden cart wheel" msgid_plural "wooden cart wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda de madera para carro" +msgstr[1] "ruedas de madera para carro" +msgstr[2] "ruedas de madera para carro" #. ~ Description for {'str': 'wooden cart wheel'} #: data/json/items/vehicle/wheel.json @@ -121737,9 +122029,9 @@ msgstr "Una rueda de madera para carro, hecha a mano." #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "banded wooden cart wheel" msgid_plural "banded wooden cart wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rueda reforzada de madera para carro" +msgstr[1] "ruedas reforzada de madera para carro" +msgstr[2] "ruedas reforzada de madera para carro" #. ~ Description for {'str': 'banded wooden cart wheel'} #: data/json/items/vehicle/wheel.json @@ -123349,9 +123641,9 @@ msgstr "" #: data/json/monsters/bird.json msgid "chicken" msgid_plural "chickens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pollo" +msgstr[1] "pollos" +msgstr[2] "pollos" #. ~ Description for {'str': 'chicken'} #: data/json/monsters/bird.json @@ -123383,9 +123675,9 @@ msgstr "" #: data/json/monsters/bird.json msgid "crow" msgid_plural "crows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cuervo" +msgstr[1] "cuervos" +msgstr[2] "cuervos" #. ~ Description for {'str': 'crow'} #: data/json/monsters/bird.json @@ -123399,9 +123691,9 @@ msgstr "" #: data/json/monsters/bird.json msgid "duck" msgid_plural "ducks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pato" +msgstr[1] "patos" +msgstr[2] "patos" #. ~ Description for {'str': 'duck'} #: data/json/monsters/bird.json @@ -123427,9 +123719,9 @@ msgstr "" #: data/json/monsters/bird.json msgid "turkey" msgid_plural "turkeys" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pavo" +msgstr[1] "pavos" +msgstr[2] "pavos" #. ~ Description for {'str': 'turkey'} #: data/json/monsters/bird.json @@ -123529,9 +123821,9 @@ msgstr "" #: data/json/monsters/cyborgs.json msgid "broken cyborg" msgid_plural "broken cyborgs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cyborg roto" +msgstr[1] "cyborgs rotos" +msgstr[2] "cyborgs rotos" #. ~ Description for {'str': 'broken cyborg'} #: data/json/monsters/cyborgs.json @@ -123549,9 +123841,9 @@ msgstr "" #: data/json/monsters/cyborgs.json msgid "prototype cyborg" msgid_plural "prototype cyborgs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "prototipo de ciborg" +msgstr[1] "prototipos de ciborg" +msgstr[2] "prototipos de ciborg" #. ~ Description for {'str': 'prototype cyborg'} #: data/json/monsters/cyborgs.json @@ -123565,9 +123857,9 @@ msgstr "" #: data/json/monsters/defense_bot.json msgid "police bot" msgid_plural "police bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "policíabot" +msgstr[1] "policíabots" +msgstr[2] "policíabots" #. ~ Description for {'str': 'police bot'} #: data/json/monsters/defense_bot.json @@ -123586,9 +123878,9 @@ msgstr "" #: data/json/monsters/defense_bot.json msgid "riot control bot" msgid_plural "riot control bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "antidisturbot" +msgstr[1] "antidisturbots" +msgstr[2] "antidisturbots" #. ~ Description for {'str': 'riot control bot'} #: data/json/monsters/defense_bot.json @@ -123636,9 +123928,9 @@ msgstr "" #: data/mods/Modular_Turrets/monster_override.json msgid "skitterbot" msgid_plural "skitterbots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arañabot" +msgstr[1] "arañabots" +msgstr[2] "arañabots" #. ~ Description for {'str': 'skitterbot'} #. ~ Description for skitterbot @@ -123797,9 +124089,9 @@ msgstr "" #: data/json/monsters/drones.json msgid "manhack" msgid_plural "manhacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "manhack" +msgstr[1] "manhacks" +msgstr[2] "manhacks" #. ~ Description for {'str': 'manhack'} #: data/json/monsters/drones.json @@ -124180,9 +124472,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "trout" msgid_plural "trouts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trucha" +msgstr[1] "truchas" +msgstr[2] "truchas" #. ~ Description for {'str': 'trout'} #: data/json/monsters/fish.json @@ -124264,9 +124556,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "salmon" msgid_plural "salmons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salmón" +msgstr[1] "salmones" +msgstr[2] "salmones" #. ~ Description for {'str': 'salmon'} #: data/json/monsters/fish.json @@ -124315,9 +124607,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "whitefish" msgid_plural "whitefish" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bacalao" +msgstr[1] "bacalaos" +msgstr[2] "bacalaos" #. ~ Description for {'str_sp': 'whitefish'} #: data/json/monsters/fish.json @@ -124331,9 +124623,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "largemouth bass" msgid_plural "largemouth bass" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perca americana" +msgstr[1] "percas americanas" +msgstr[2] "percas americanas" #. ~ Description for {'str_sp': 'largemouth bass'} #: data/json/monsters/fish.json @@ -124344,9 +124636,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "smallmouth bass" msgid_plural "smallmouth bass" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perca americana de boca pequeña " +msgstr[1] "percas americanas de boca pequeña" +msgstr[2] "percas americanas de boca pequeña" #. ~ Description for {'str_sp': 'smallmouth bass'} #: data/json/monsters/fish.json @@ -124358,9 +124650,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "striped bass" msgid_plural "striped bass" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perca americana rayada" +msgstr[1] "percas americanas rayada" +msgstr[2] "percas americanas rayada" #. ~ Description for {'str_sp': 'striped bass'} #: data/json/monsters/fish.json @@ -124388,9 +124680,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "perch" msgid_plural "perches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lucioperca" +msgstr[1] "luciopercas" +msgstr[2] "luciopercas" #. ~ Description for {'str': 'perch', 'str_pl': 'perches'} #: data/json/monsters/fish.json @@ -124414,9 +124706,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "sunfish" msgid_plural "sunfish" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "peces sol" +msgstr[1] "pez sol" +msgstr[2] "pez sol" #. ~ Description for {'str_sp': 'sunfish'} #: data/json/monsters/fish.json @@ -124438,9 +124730,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "bluegill" msgid_plural "bluegills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mojarra de agallas azules" +msgstr[1] "mojarras de agallas azules" +msgstr[2] "mojarras de agallas azules" #. ~ Description for {'str': 'bluegill'} #: data/json/monsters/fish.json @@ -124541,9 +124833,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "bullhead" msgid_plural "bullheads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "siluro" +msgstr[1] "siluros" +msgstr[2] "siluros" #. ~ Description for {'str': 'bullhead'} #: data/json/monsters/fish.json @@ -124578,9 +124870,9 @@ msgstr "" msgctxt "fish" msgid "pike" msgid_plural "pikes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lucio" +msgstr[1] "lucios" +msgstr[2] "lucios" #. ~ Description for {'ctxt': 'fish', 'str': 'pike'} #: data/json/monsters/fish.json @@ -124630,9 +124922,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "carp" msgid_plural "carps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carpa" +msgstr[1] "carpas" +msgstr[2] "carpas" #. ~ Description for {'str': 'carp'} #: data/json/monsters/fish.json @@ -124656,9 +124948,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "bowfin" msgid_plural "bowfins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "amia calva" +msgstr[1] "amias calva" +msgstr[2] "amias calva" #. ~ Description for {'str': 'bowfin'} #: data/json/monsters/fish.json @@ -124725,9 +125017,9 @@ msgstr "Un extraño pez de tres ojos." #: data/json/monsters/fish.json msgid "freshwater eel" msgid_plural "freshwater eels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anguila de agua dulce" +msgstr[1] "anguilas de agua dulce" +msgstr[2] "anguilas de agua dulce" #. ~ Description for {'str': 'freshwater eel'} #: data/json/monsters/fish.json @@ -124777,9 +125069,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "giant carp" msgid_plural "giant carps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carpa gigante" +msgstr[1] "carpas gigantes" +msgstr[2] "carpas gigantes" #. ~ Description for {'str': 'giant carp'} #: data/json/monsters/fish.json @@ -124793,9 +125085,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "giant salmon" msgid_plural "giant salmons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salmón gigante" +msgstr[1] "salmones gigantes" +msgstr[2] "salmones gigantes" #. ~ Description for {'str': 'giant salmon'} #: data/json/monsters/fish.json @@ -124809,9 +125101,9 @@ msgstr "" #: data/json/monsters/fish.json msgid "seweranha" msgid_plural "seweranhas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "piraña de cloaca" +msgstr[1] "pirañas de cloaca" +msgstr[2] "pirañas de cloaca" #. ~ Description for {'str': 'seweranha'} #: data/json/monsters/fish.json @@ -124825,9 +125117,9 @@ msgstr "" #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal boomer" msgid_plural "fungal boomers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "boomer con hongos" +msgstr[1] "boomers con hongos" +msgstr[2] "boomers con hongos" #. ~ Description for {'str': 'fungal boomer'} #: data/json/monsters/fungus.json @@ -124841,9 +125133,9 @@ msgstr "" #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal blossom" msgid_plural "fungal blossoms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capullo fúngico" +msgstr[1] "capullos fúngicos" +msgstr[2] "capullos fúngicos" #. ~ Description for {'str': 'fungal blossom'} #: data/json/monsters/fungus.json @@ -124857,9 +125149,9 @@ msgstr "" #: data/json/monsters/fungus.json msgid "fungal hedgerow" msgid_plural "fungal hedgerows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "seto fúngico" +msgstr[1] "setos fúngicos" +msgstr[2] "setos fúngicos" #. ~ Description for {'str': 'fungal hedgerow'} #: data/json/monsters/fungus.json @@ -124874,9 +125166,9 @@ msgstr "" #: data/json/monsters/fungus.json msgid "fungal tendril" msgid_plural "fungal tendrils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zarcillo fúngico" +msgstr[1] "zarcillos fúngicos" +msgstr[2] "zarcillos fúngicos" #. ~ Description for {'str': 'fungal tendril'} #: data/json/monsters/fungus.json @@ -124896,9 +125188,9 @@ msgstr "" #: data/mods/Limit Fungal Growth/modinfo.json msgid "fungaloid" msgid_plural "fungaloids" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fungaloide" +msgstr[1] "fungaloides" +msgstr[2] "fungaloides" #. ~ Description for {'str': 'fungaloid'} #: data/json/monsters/fungus.json @@ -124915,9 +125207,9 @@ msgstr "" #: data/json/monsters/fungus.json msgid "fungal spire" msgid_plural "fungal spires" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torre fúngica" +msgstr[1] "torres fúngicas" +msgstr[2] "torres fúngicas" #. ~ Description for {'str': 'fungal spire'} #: data/json/monsters/fungus.json @@ -124931,9 +125223,9 @@ msgstr "" #: data/json/monsters/fungus.json msgid "giant fungal blossom" msgid_plural "giant fungal blossoms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capullo fúngico gigante" +msgstr[1] "capullos fúngicos gigantes" +msgstr[2] "capullos fúngicos gigantes" #. ~ Description for {'str': 'giant fungal blossom'} #: data/json/monsters/fungus.json @@ -124950,9 +125242,9 @@ msgstr "" #: data/mods/alt_map_key/overmap_terrain.json msgid "fungal tower" msgid_plural "fungal towers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torre fúngica" +msgstr[1] "torres fúngicas" +msgstr[2] "torres fúngicas" #. ~ Description for {'str': 'fungal tower'} #: data/json/monsters/fungus.json @@ -124972,9 +125264,9 @@ msgstr "" #: data/json/monsters/fungus.json msgid "fungal sporeling" msgid_plural "fungal sporelings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espora fúngica" +msgstr[1] "esporas fúngicas" +msgstr[2] "esporas fúngicas" #. ~ Description for {'str': 'fungal sporeling'} #: data/json/monsters/fungus.json @@ -124990,9 +125282,9 @@ msgstr "" #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "spore cloud" msgid_plural "spore clouds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nube de esporas" +msgstr[1] "nubes de esporas" +msgstr[2] "nubes de esporas" #. ~ Description for {'str': 'spore cloud'} #: data/json/monsters/fungus.json @@ -125002,9 +125294,9 @@ msgstr "Es una masa de esporas del tamaño de puños flotando por el aire." #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal zombie" msgid_plural "fungal zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi con hongos" +msgstr[1] "zombis con hongos" +msgstr[2] "zombis con hongos" #. ~ Description for {'str': 'fungal zombie'} #: data/json/monsters/fungus.json @@ -125081,9 +125373,9 @@ msgstr "" #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal ant" msgid_plural "fungal ants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hormiga fúngica" +msgstr[1] "hormigas fúngicas" +msgstr[2] "hormigas fúngicas" #. ~ Description for {'str': 'fungal ant'} #: data/json/monsters/fungus.json @@ -125113,9 +125405,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "dark wyrm" msgid_plural "dark wyrms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "wyrm oscuro" +msgstr[1] "wyrms oscuros" +msgstr[2] "wyrms oscuros" #. ~ Description for {'str': 'dark wyrm'} #: data/json/monsters/insect_spider.json @@ -125131,9 +125423,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "graboid" msgid_plural "graboids" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "graboid" +msgstr[1] "graboides" +msgstr[2] "graboides" #. ~ Description for {'str': 'graboid'} #: data/json/monsters/insect_spider.json @@ -125150,9 +125442,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "half worm" msgid_plural "half worms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mediogusano" +msgstr[1] "mediogusanos" +msgstr[2] "mediogusanos" #. ~ Description for {'str': 'half worm'} #: data/json/monsters/insect_spider.json @@ -125162,9 +125454,9 @@ msgstr "Una parte movediza cortada de un gusano gigante herido." #: data/json/monsters/insect_spider.json msgid "giant worm" msgid_plural "giant worms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gusano gigante" +msgstr[1] "gusanos gigantes" +msgstr[2] "gusanos gigantes" #. ~ Description for {'str': 'giant worm'} #: data/json/monsters/insect_spider.json @@ -125261,9 +125553,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant bee" msgid_plural "giant bees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "abeja gigante" +msgstr[1] "abejas gigantes" +msgstr[2] "abejas gigantes" #. ~ Description for {'str': 'giant bee'} #: data/json/monsters/insect_spider.json @@ -125278,9 +125570,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant centipede" msgid_plural "giant centipedes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Ciempiés gigante" +msgstr[1] "Ciempiés gigantes" +msgstr[2] "Ciempiés gigantes" #. ~ Description for {'str': 'giant centipede'} #: data/json/monsters/insect_spider.json @@ -125326,9 +125618,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant mosquito" msgid_plural "giant mosquitos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosquito gigante" +msgstr[1] "mosquitos gigantes" +msgstr[2] "mosquitos gigantes" #. ~ Description for {'str': 'giant mosquito'} #: data/json/monsters/insect_spider.json @@ -125376,9 +125668,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant jumping spider" msgid_plural "giant jumping spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña saltarina gigante" +msgstr[1] "arañas saltarinas gigantes" +msgstr[2] "arañas saltarinas gigantes" #. ~ Description for {'str': 'giant jumping spider'} #: data/json/monsters/insect_spider.json @@ -125392,9 +125684,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant trapdoor spider" msgid_plural "giant trapdoor spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña tapadera gigante" +msgstr[1] "arañas tapadera gigantes" +msgstr[2] "arañas tapadera gigantes" #. ~ Description for {'str': 'giant trapdoor spider'} #: data/json/monsters/insect_spider.json @@ -125408,9 +125700,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant web spider" msgid_plural "giant web spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña gigante" +msgstr[1] "arañas gigantes" +msgstr[2] "arañas gigantes" #. ~ Description for {'str': 'giant web spider'} #: data/json/monsters/insect_spider.json @@ -125424,9 +125716,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "immature giant web spider" msgid_plural "immature giant web spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña gigante inmadura" +msgstr[1] "arañas gigantes inmaduras" +msgstr[2] "arañas gigantes inmaduras" #. ~ Description for {'str': 'immature giant web spider'} #: data/json/monsters/insect_spider.json @@ -125440,9 +125732,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant black widow" msgid_plural "giant black widows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "viuda negra gigante" +msgstr[1] "viudas negras gigantes" +msgstr[2] "viudas negras gigantes" #. ~ Description for {'str': 'giant black widow'} #: data/json/monsters/insect_spider.json @@ -125456,9 +125748,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant black widow spiderling" msgid_plural "giant black widow spiderlings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cría de viuda negra gigante" +msgstr[1] "crías de viuda negra gigante" +msgstr[2] "crías de viuda negra gigante" #. ~ Description for {'str': 'giant black widow spiderling'} #: data/json/monsters/insect_spider.json @@ -125472,9 +125764,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant wolf spider" msgid_plural "giant wolf spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña-lobo gigante" +msgstr[1] "arañas-lobo gigantes" +msgstr[2] "arañas-lobo gigantes" #. ~ Description for {'str': 'giant wolf spider'} #: data/json/monsters/insect_spider.json @@ -125488,9 +125780,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant wasp" msgid_plural "giant wasps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "avispa gigante" +msgstr[1] "avispas gigantes" +msgstr[2] "avispas gigantes" #. ~ Description for {'str': 'giant wasp'} #: data/json/monsters/insect_spider.json @@ -125505,9 +125797,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "dermatik" msgid_plural "dermatiks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dermatik" +msgstr[1] "dermatiks" +msgstr[2] "dermatiks" #. ~ Description for {'str': 'dermatik'} #: data/json/monsters/insect_spider.json @@ -125537,9 +125829,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant ant" msgid_plural "giant ants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hormiga gigante" +msgstr[1] "hormigas gigantes" +msgstr[2] "hormigas gigantes" #. ~ Description for {'str': 'giant ant'} #: data/json/monsters/insect_spider.json @@ -125570,9 +125862,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "acidic ant larva" msgid_plural "acidic ant larvae" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "larva de hormiga ácida" +msgstr[1] "larvas de hormiga ácida" +msgstr[2] "larvas de hormiga ácida" #. ~ Description for {'str': 'acidic ant larva', 'str_pl': 'acidic ant #. larvae'} @@ -125588,9 +125880,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "acidic queen ant" msgid_plural "acidic queen ants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hormiga ácida reina" +msgstr[1] "hormigas ácidas reina" +msgstr[2] "hormigas ácidas reina" #. ~ Description for {'str': 'acidic queen ant'} #: data/json/monsters/insect_spider.json @@ -125607,9 +125899,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "acidic soldier ant" msgid_plural "acidic soldier ants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hormiga ácida soldado" +msgstr[1] "hormigas ácidas soldado" +msgstr[2] "hormigas ácidas soldado" #. ~ Description for {'str': 'acidic soldier ant'} #: data/json/monsters/insect_spider.json @@ -125625,9 +125917,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "ant larva" msgid_plural "ant larvae" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "larva de hormiga" +msgstr[1] "larvas de hormiga" +msgstr[2] "larvas de hormiga" #. ~ Description for {'str': 'ant larva', 'str_pl': 'ant larvae'} #: data/json/monsters/insect_spider.json @@ -125641,9 +125933,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "queen ant" msgid_plural "queen ants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hormiga reina" +msgstr[1] "hormigas reinas" +msgstr[2] "hormigas reinas" #. ~ Description for {'str': 'queen ant'} #: data/json/monsters/insect_spider.json @@ -125657,9 +125949,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "soldier ant" msgid_plural "soldier ants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hormiga soldado" +msgstr[1] "hormigas soldado" +msgstr[2] "hormigas soldado" #. ~ Description for {'str': 'soldier ant'} #: data/json/monsters/insect_spider.json @@ -125673,9 +125965,9 @@ msgstr "" #: data/json/monsters/insect_spider.json msgid "giant locust" msgid_plural "giant locusts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "langosta gigante" +msgstr[1] "langostas gigantes" +msgstr[2] "langostas gigantes" #. ~ Description for {'str': 'giant locust'} #: data/json/monsters/insect_spider.json @@ -125720,9 +126012,9 @@ msgstr "" #: data/json/monsters/jabberwock.json msgid "flesh golem" msgid_plural "flesh golems" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "golem de carne" +msgstr[1] "golems de carne" +msgstr[2] "golems de carne" #. ~ Description for {'str': 'flesh golem'} #: data/json/monsters/jabberwock.json @@ -125735,9 +126027,9 @@ msgstr "" #: data/json/monsters/jabberwock.json msgid "jabberwock" msgid_plural "jabberwocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "jabberwock" +msgstr[1] "jabberwocks" +msgstr[2] "jabberwocks" #. ~ Description for {'str': 'jabberwock'} #: data/json/monsters/jabberwock.json @@ -125754,9 +126046,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "bat" msgid_plural "bats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "murciélago" +msgstr[1] "murciélagos" +msgstr[2] "murciélagos" #. ~ Description for {'str': 'bat'} #: data/json/monsters/mammal.json @@ -125789,9 +126081,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "black bear" msgid_plural "black bears" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "oso negro" +msgstr[1] "osos negros" +msgstr[2] "osos negros" #. ~ Description for {'str': 'black bear'} #: data/json/monsters/mammal.json @@ -125807,9 +126099,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "beaver" msgid_plural "beavers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "castor" +msgstr[1] "castores" +msgstr[2] "castores" #. ~ Description for {'str': 'beaver'} #: data/json/monsters/mammal.json @@ -125827,9 +126119,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "black rat" msgid_plural "black rats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rata negra" +msgstr[1] "ratas negras" +msgstr[2] "ratas negras" #. ~ Description for {'str': 'black rat'} #: data/json/monsters/mammal.json @@ -125869,9 +126161,9 @@ msgstr[2] "" #: data/json/monsters/mammal.json msgid "bobcat" msgid_plural "bobcats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gato montés" +msgstr[1] "gatos monteses" +msgstr[2] "gatos monteses" #. ~ Description for {'str': 'bobcat'} #: data/json/monsters/mammal.json @@ -125969,9 +126261,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "Siamese cat" msgid_plural "Siamese cats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gato siamés" +msgstr[1] "gatos siameses" +msgstr[2] "gatos siameses" #. ~ Description for Siamese cat #: data/json/monsters/mammal.json @@ -126194,9 +126486,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "chipmunk" msgid_plural "chipmunks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ardilla" +msgstr[1] "ardillas" +msgstr[2] "ardillas" #. ~ Description for {'str': 'chipmunk'} #: data/json/monsters/mammal.json @@ -126253,16 +126545,16 @@ msgstr "" #: data/json/monsters/mammal.json msgid "cow" msgid_plural "cows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vaca" +msgstr[1] "vacas" +msgstr[2] "vacas" #: data/json/monsters/mammal.json msgid "coyote" msgid_plural "coyotes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "coyote" +msgstr[1] "coyotes" +msgstr[2] "coyotes" #. ~ Description for {'str': 'coyote'} #: data/json/monsters/mammal.json @@ -126309,9 +126601,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "deer" msgid_plural "deers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ciervo" +msgstr[1] "ciervos" +msgstr[2] "ciervos" #. ~ Description for {'str': 'deer'} #: data/json/monsters/mammal.json @@ -126722,9 +127014,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "groundhog" msgid_plural "groundhogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "marmota" +msgstr[1] "marmotas" +msgstr[2] "marmotas" #. ~ Description for {'str': 'groundhog'} #: data/json/monsters/mammal.json @@ -126737,9 +127029,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "jackrabbit" msgid_plural "jackrabbits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "liebre" +msgstr[1] "liebres" +msgstr[2] "liebres" #. ~ Description for {'str': 'jackrabbit'} #: data/json/monsters/mammal.json @@ -126753,9 +127045,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "horse" msgid_plural "horses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caballo" +msgstr[1] "caballos" +msgstr[2] "caballos" #. ~ Description for {'str': 'horse'} #: data/json/monsters/mammal.json @@ -126769,9 +127061,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "lemming" msgid_plural "lemmings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lemming" +msgstr[1] "lemmings" +msgstr[2] "lemmings" #. ~ Description for {'str': 'lemming'} #: data/json/monsters/mammal.json @@ -126790,9 +127082,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "mink" msgid_plural "minks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "visón" +msgstr[1] "visones" +msgstr[2] "visones" #. ~ Description for {'str': 'mink'} #: data/json/monsters/mammal.json @@ -126823,9 +127115,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "muskrat" msgid_plural "muskrats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rata almizclera" +msgstr[1] "ratas almizcleras" +msgstr[2] "ratas almizcleras" #. ~ Description for {'str': 'muskrat'} #: data/json/monsters/mammal.json @@ -126858,9 +127150,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "opossum" msgid_plural "opossums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zarigüeya" +msgstr[1] "zarigüeyas" +msgstr[2] "zarigüeyas" #. ~ Description for {'str': 'opossum'} #: data/json/monsters/mammal.json @@ -126876,9 +127168,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "otter" msgid_plural "otters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nutria" +msgstr[1] "nutrias" +msgstr[2] "nutrias" #. ~ Description for {'str': 'otter'} #: data/json/monsters/mammal.json @@ -126892,9 +127184,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "piglet" msgid_plural "piglets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lechón" +msgstr[1] "lechones" +msgstr[2] "lechones" #. ~ Description for {'str': 'piglet'} #: data/json/monsters/mammal.json @@ -126907,9 +127199,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "pig" msgid_plural "pigs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cerdo" +msgstr[1] "cerdos" +msgstr[2] "cerdos" #. ~ Description for {'str': 'pig'} #: data/json/monsters/mammal.json @@ -126923,9 +127215,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "rabbit" msgid_plural "rabbits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "conejo" +msgstr[1] "conejos" +msgstr[2] "conejos" #. ~ Description for {'str': 'rabbit'} #: data/json/monsters/mammal.json @@ -126939,9 +127231,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "raccoon" msgid_plural "raccoons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mapache" +msgstr[1] "mapaches" +msgstr[2] "mapaches" #. ~ Description for {'str': 'raccoon'} #: data/json/monsters/mammal.json @@ -126957,9 +127249,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "rat king" msgid_plural "rat kings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rata rey" +msgstr[1] "ratas rey" +msgstr[2] "ratas rey" #. ~ Description for {'str': 'rat king'} #: data/json/monsters/mammal.json @@ -126974,9 +127266,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "sewer rat" msgid_plural "sewer rats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rata de cloaca" +msgstr[1] "ratas de cloaca" +msgstr[2] "ratas de cloaca" #. ~ Description for {'str': 'sewer rat'} #: data/json/monsters/mammal.json @@ -127018,9 +127310,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "squirrel" msgid_plural "squirrels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ardilla" +msgstr[1] "ardillas" +msgstr[2] "ardillas" #. ~ Description for {'str': 'squirrel'} #: data/json/monsters/mammal.json @@ -127048,9 +127340,9 @@ msgstr "" #: data/json/monsters/mammal.json msgid "weasel" msgid_plural "weasels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "comadreja" +msgstr[1] "comadrejas" +msgstr[2] "comadrejas" #. ~ Description for {'str': 'weasel'} #: data/json/monsters/mammal.json @@ -127162,9 +127454,9 @@ msgstr "" #: data/json/monsters/mi-go.json msgid "mi-go" msgid_plural "mi-gos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mi-go" +msgstr[1] "mi-gos" +msgstr[2] "mi-gos" #. ~ Description for {'str': 'mi-go'} #: data/json/monsters/mi-go.json @@ -127279,9 +127571,9 @@ msgstr "" #: data/json/monsters/misc.json msgid "debug monster" msgid_plural "debug monsters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "monstruo de depuración" +msgstr[1] "monstruos de depuración" +msgstr[2] "monstruos de depuración" #. ~ Description for {'str': 'debug monster'} #: data/json/monsters/misc.json @@ -127320,9 +127612,9 @@ msgstr "" #: data/json/monsters/misc.json msgid "generator" msgid_plural "generators" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "generador" +msgstr[1] "generadores" +msgstr[2] "generadores" #. ~ Description for {'str': 'generator'} #: data/json/monsters/misc.json @@ -127335,9 +127627,9 @@ msgstr "" #: data/json/monsters/misc.json msgid "your mother" msgid_plural "your mothers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tu madre" +msgstr[1] "tus madres" +msgstr[2] "tus madres" #. ~ Description for {'str': 'your mother'} #: data/json/monsters/misc.json @@ -127347,9 +127639,9 @@ msgstr "¿Mamá?" #: data/json/monsters/misc.json msgid "evil multi-cooker" msgid_plural "evil multi-cookers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "multicocina malévola" +msgstr[1] "multicocinas malévolas" +msgstr[2] "multicocinas malévolas" #. ~ Description for {'str': 'evil multi-cooker'} #: data/json/monsters/misc.json @@ -127359,9 +127651,9 @@ msgstr "¡Esta cocina malévola tiene vida propia! ¡Cuidado!" #: data/json/monsters/misc.json data/mods/Magiclysm/monsters.json msgid "hologram" msgid_plural "holograms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "holograma" +msgstr[1] "hologramas" +msgstr[2] "hologramas" #. ~ Description for {'str': 'hologram'} #. ~ Description for hologram @@ -127387,9 +127679,9 @@ msgstr "" #: data/json/monsters/mutant_human.json msgid "C.H.U.D." msgid_plural "C.H.U.D.s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "H.H.S.C." +msgstr[1] "H.H.S.C." +msgstr[2] "H.H.S.C." #. ~ Description for {'str': 'C.H.U.D.'} #: data/json/monsters/mutant_human.json @@ -127435,9 +127727,9 @@ msgstr "" #: data/json/monsters/mutant_human.json msgid "cyclopean" msgid_plural "cyclopeans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ciclópeo" +msgstr[1] "ciclópeos" +msgstr[2] "ciclópeos" #. ~ Description for {'str': 'cyclopean'} #: data/json/monsters/mutant_human.json @@ -127451,9 +127743,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "albino penguin" msgid_plural "albino penguins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pingüino albino" +msgstr[1] "pingüinos albino" +msgstr[2] "pingüinos albino" #. ~ Description for {'str': 'albino penguin'} #: data/json/monsters/nether.json @@ -127466,9 +127758,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "amigara horror" msgid_plural "amigara horrors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "horror amigara" +msgstr[1] "horrores amigara" +msgstr[2] "horrores amigara" #. ~ Description for {'str': 'amigara horror'} #: data/json/monsters/nether.json @@ -127508,9 +127800,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "blood sacrifice" msgid_plural "blood sacrifices" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sacrificio sangriento" +msgstr[1] "sacrificios sangrientos" +msgstr[2] "sacrificios sangrientos" #. ~ Description for {'str': 'blood sacrifice'} #: data/json/monsters/nether.json @@ -127527,9 +127819,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "breather" msgid_plural "breathers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "respirador" +msgstr[1] "respiradores" +msgstr[2] "respiradores" #. ~ Description for {'str': 'breather'} #: data/json/monsters/nether.json @@ -127551,9 +127843,9 @@ msgstr "Es una rara masa de viscosidad rosa inmóvil. Parece respirar." #: data/json/monsters/nether.json msgid "wraith" msgid_plural "wraiths" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espectro" +msgstr[1] "espectros" +msgstr[2] "espectros" #. ~ Description for {'str': 'wraith'} #: data/json/monsters/nether.json @@ -127565,9 +127857,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "dementia" msgid_plural "dementias" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dementia" +msgstr[1] "dementias" +msgstr[2] "dementias" #. ~ Description for {'str': 'dementia'} #: data/json/monsters/nether.json @@ -127581,9 +127873,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "dog" msgid_plural "dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perro" +msgstr[1] "perros" +msgstr[2] "perros" #. ~ Description for {'str': 'dog'} #: data/json/monsters/nether.json @@ -127597,9 +127889,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "flaming eye" msgid_plural "flaming eyes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ojo llameante" +msgstr[1] "ojos llameantes" +msgstr[2] "ojos llameantes" #. ~ Description for {'str': 'flaming eye'} #: data/json/monsters/nether.json @@ -127620,9 +127912,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "flesh angel" msgid_plural "flesh angels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ángel cárnico" +msgstr[1] "ángeles cárnicos" +msgstr[2] "ángeles cárnicos" #. ~ Description for {'str': 'flesh angel'} #: data/json/monsters/nether.json @@ -127636,9 +127928,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "flying polyp" msgid_plural "flying polyps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pólipo volador" +msgstr[1] "pólipos voladores" +msgstr[2] "pólipos voladores" #. ~ Description for {'str': 'flying polyp'} #: data/json/monsters/nether.json @@ -127651,9 +127943,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "gozu" msgid_plural "gozus" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gozu" +msgstr[1] "gozus" +msgstr[2] "gozus" #. ~ Description for {'str': 'gozu'} #: data/json/monsters/nether.json @@ -127674,9 +127966,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "gracken" msgid_plural "grackens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gracken" +msgstr[1] "grackens" +msgstr[2] "grackens" #. ~ Description for {'str': 'gracken'} #: data/json/monsters/nether.json @@ -127698,9 +127990,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "tentacle dog" msgid_plural "tentacle dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perro tentáculo" +msgstr[1] "perros tentáculo" +msgstr[2] "perros tentáculo" #. ~ Description for {'str': 'tentacle dog'} #: data/json/monsters/nether.json @@ -127749,9 +128041,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "human snail" msgid_plural "human snails" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caracol humano" +msgstr[1] "caracoles humanos" +msgstr[2] "caracoles humanos" #. ~ Description for {'str': 'human snail'} #: data/json/monsters/nether.json @@ -127765,9 +128057,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "hunting horror" msgid_plural "hunting horrors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "horror cazador" +msgstr[1] "horrores cazador" +msgstr[2] "horrores cazador" #. ~ Description for {'str': 'hunting horror'} #: data/json/monsters/nether.json @@ -127785,9 +128077,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "kreck" msgid_plural "krecks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "kreck" +msgstr[1] "krecks" +msgstr[2] "krecks" #. ~ Description for {'str': 'kreck'} #: data/json/monsters/nether.json @@ -127825,9 +128117,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "shadow snake" msgid_plural "shadow snakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "serpiente de sombra" +msgstr[1] "serpientes de sombra" +msgstr[2] "serpientes de sombra" #. ~ Description for {'str': 'shadow snake'} #: data/json/monsters/nether.json @@ -127842,9 +128134,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "shoggoth" msgid_plural "shoggoths" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "shoggoth" +msgstr[1] "shoggoths" +msgstr[2] "shoggoths" #. ~ Description for {'str': 'shoggoth'} #: data/json/monsters/nether.json @@ -127860,9 +128152,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "thing" msgid_plural "things" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cosa" +msgstr[1] "cosas" +msgstr[2] "cosas" #. ~ Description for {'str': 'thing'} #: data/json/monsters/nether.json @@ -127893,9 +128185,9 @@ msgstr "" #: data/json/monsters/nether.json msgid "yugg" msgid_plural "yuggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "yugg" +msgstr[1] "yuggs" +msgstr[2] "yuggs" #. ~ Description for {'str': 'yugg'} #: data/json/monsters/nether.json @@ -128047,9 +128339,9 @@ msgstr "" #: data/json/monsters/reptile_amphibian.json msgid "giant frog" msgid_plural "giant frogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rana gigante" +msgstr[1] "ranas gigantes" +msgstr[2] "ranas gigantes" #. ~ Description for {'str': 'giant frog'} #: data/json/monsters/reptile_amphibian.json @@ -128079,9 +128371,9 @@ msgstr "" #: data/json/monsters/reptile_amphibian.json msgid "rattlesnake" msgid_plural "rattlesnakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "serpiente de cascabel" +msgstr[1] "serpientes de cascabel" +msgstr[2] "serpientes de cascabel" #. ~ Description for {'str': 'rattlesnake'} #: data/json/monsters/reptile_amphibian.json @@ -128114,9 +128406,9 @@ msgstr "" #: data/json/monsters/reptile_amphibian.json msgid "sewer snake" msgid_plural "sewer snakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "serpiente de cloaca" +msgstr[1] "serpientes de cloaca" +msgstr[2] "serpientes de cloaca" #. ~ Description for {'str': 'sewer snake'} #: data/json/monsters/reptile_amphibian.json @@ -128129,13 +128421,6 @@ msgstr "" "pálido por su vida subterránea. Se mueve en manada por debajo del suelo y su" " nombre es por su hábito de infestar las cloacas." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -128148,9 +128433,9 @@ msgstr "" #: data/json/monsters/slimes.json msgid "brain blob" msgid_plural "brain blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "masa con cerebro" +msgstr[1] "masas con cerebro" +msgstr[2] "masas con cerebro" #. ~ Description for {'str': 'brain blob'} #: data/json/monsters/slimes.json @@ -128165,9 +128450,9 @@ msgstr "" #: data/json/monsters/slimes.json msgid "big blob" msgid_plural "big blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "masa grande" +msgstr[1] "masas grandes" +msgstr[2] "masas grandes" #. ~ Description for {'str': 'big blob'} #: data/json/monsters/slimes.json @@ -128181,9 +128466,9 @@ msgstr "" #: data/json/monsters/slimes.json msgid "small blob" msgid_plural "small blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "masa pequeña" +msgstr[1] "masas pequeñas" +msgstr[2] "masas pequeñas" #. ~ Description for {'str': 'small blob'} #: data/json/monsters/slimes.json @@ -128197,9 +128482,9 @@ msgstr "" #: data/json/monsters/slimes.json msgid "amoebic mold" msgid_plural "amoebic molds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "moho amebiano" +msgstr[1] "mohos amebianos" +msgstr[2] "mohos amebianos" #. ~ Description for {'str': 'amoebic mold'} #: data/json/monsters/slimes.json @@ -128213,9 +128498,9 @@ msgstr "" #: data/json/monsters/slimes.json msgid "slimespring" msgid_plural "slimesprings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "slime elástico" +msgstr[1] "slimes elásticos" +msgstr[2] "slimes elásticos" #. ~ Description for {'str': 'slimespring'} #: data/json/monsters/slimes.json @@ -128227,9 +128512,9 @@ msgstr "" #: data/json/monsters/slugs.json msgid "sludge crawler" msgid_plural "sludge crawlers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arrastrador de barro" +msgstr[1] "arrastradores de barro" +msgstr[2] "arrastradores de barro" #. ~ Description for {'str': 'sludge crawler'} #: data/json/monsters/slugs.json @@ -128246,9 +128531,9 @@ msgstr "" #: data/json/monsters/slugs.json msgid "giant slug" msgid_plural "giant slugs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "babosa gigante" +msgstr[1] "babosas gigantes" +msgstr[2] "babosas gigantes" #. ~ Description for {'str': 'giant slug'} #: data/json/monsters/slugs.json @@ -128292,9 +128577,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "biollante" msgid_plural "biollantes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "biollante" +msgstr[1] "biollantes" +msgstr[2] "biollantes" #. ~ Description for {'str': 'biollante'} #: data/json/monsters/triffid.json @@ -128308,9 +128593,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "creeper hub" msgid_plural "creeper hubs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "enredadera central" +msgstr[1] "enredaderas centrales" +msgstr[2] "enredaderas centrales" #. ~ Description for {'str': 'creeper hub'} #: data/json/monsters/triffid.json @@ -128324,9 +128609,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "creeper vine" msgid_plural "creeper vines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "enredadera brotada" +msgstr[1] "enredaderas brotadas" +msgstr[2] "enredaderas brotadas" #. ~ Description for {'str': 'creeper vine'} #: data/json/monsters/triffid.json @@ -128354,9 +128639,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "triffid sprout" msgid_plural "triffid sprouts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brote de trífido" +msgstr[1] "brotes de trífido" +msgstr[2] "brotes de trífido" #. ~ Description for {'str': 'triffid sprout'} #: data/json/monsters/triffid.json @@ -128370,9 +128655,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "triffid" msgid_plural "triffids" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trífido" +msgstr[1] "trífidos" +msgstr[2] "trífidos" #. ~ Description for {'str': 'triffid'} #: data/json/monsters/triffid.json @@ -128388,9 +128673,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "triffid queen" msgid_plural "triffid queens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trífido reina" +msgstr[1] "trífidos reina" +msgstr[2] "trífidos reina" #. ~ Description for {'str': 'triffid queen'} #: data/json/monsters/triffid.json @@ -128406,9 +128691,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "vine beast" msgid_plural "vine beasts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bestia enredadera" +msgstr[1] "bestias enredaderas" +msgstr[2] "bestias enredaderas" #. ~ Description for {'str': 'vine beast'} #: data/json/monsters/triffid.json @@ -128424,9 +128709,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "fungal fighter" msgid_plural "fungal fighters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guerrero fúngico" +msgstr[1] "guerreros fúngicos" +msgstr[2] "guerreros fúngicos" #. ~ Description for {'str': 'fungal fighter'} #: data/json/monsters/triffid.json @@ -128442,9 +128727,9 @@ msgstr "" #: data/json/monsters/triffid.json msgid "triffid flower" msgid_plural "triffid flowers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trífido flor" +msgstr[1] "trífidos flor" +msgstr[2] "trífidos flor" #. ~ Description for {'str': 'triffid flower'} #: data/json/monsters/triffid.json @@ -128458,9 +128743,9 @@ msgstr "" #: data/mods/alt_map_key/overmap_terrain.json msgid "triffid heart" msgid_plural "triffid hearts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trífido corazón" +msgstr[1] "trífidos corazón" +msgstr[2] "trífidos corazón" #. ~ Description for {'str': 'triffid heart'} #: data/json/monsters/triffid.json @@ -128474,9 +128759,9 @@ msgstr "" #: data/json/monsters/turrets.json msgid "milspec searchlight" msgid_plural "milspec searchlights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "foco reflector milspec" +msgstr[1] "focos reflectores milspec" +msgstr[2] "focos reflectores milspec" #. ~ Description for {'str': 'milspec searchlight'} #: data/json/monsters/turrets.json @@ -128493,9 +128778,9 @@ msgstr "" #: data/mods/No_Hope/monsters.json msgid "laser turret" msgid_plural "laser turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta láser" +msgstr[1] "torretas láser" +msgstr[2] "torretas láser" #. ~ Description for {'str': 'laser turret'} #: data/json/monsters/turrets.json @@ -128588,9 +128873,9 @@ msgstr "" #: data/mods/Modular_Turrets/monster_override.json msgid "eyebot" msgid_plural "eyebots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ojobot" +msgstr[1] "ojobots" +msgstr[2] "ojobots" #. ~ Description for {'str': 'eyebot'} #: data/json/monsters/utility_bot.json @@ -128638,9 +128923,9 @@ msgstr "" #: data/json/monsters/utility_bot.json msgid "cleaner bot" msgid_plural "cleaner bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "robot de limpieza" +msgstr[1] "robots de limpieza" +msgstr[2] "robots de limpieza" #. ~ Description for {'str': 'cleaner bot'} #: data/json/monsters/utility_bot.json @@ -128671,9 +128956,9 @@ msgstr "" #: data/json/monsters/utility_bot.json msgid "miner bot" msgid_plural "miner bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "robot anti-minas" +msgstr[1] "robots anti-minas" +msgstr[2] "robots anti-minas" #. ~ Description for {'str': 'miner bot'} #: data/json/monsters/utility_bot.json @@ -128703,9 +128988,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "jawed terror" msgid_plural "jawed terrors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "terror dentado" +msgstr[1] "terrores dentados" +msgstr[2] "terrores dentados" #. ~ Description for {'str': 'jawed terror'} #: data/json/monsters/zed-animal.json @@ -128719,9 +129004,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "zombie dog" msgid_plural "zombie dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perro zombi" +msgstr[1] "perros zombis" +msgstr[2] "perros zombis" #. ~ Description for {'str': 'zombie dog'} #: data/json/monsters/zed-animal.json @@ -128735,9 +129020,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "skeletal dog" msgid_plural "skeletal dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perro esquelético" +msgstr[1] "perros esqueléticos" +msgstr[2] "perros esqueléticos" #. ~ Description for {'str': 'skeletal dog'} #: data/json/monsters/zed-animal.json @@ -128755,9 +129040,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "Z-9" msgid_plural "Z-9s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Z-9" +msgstr[1] "Z-9s" +msgstr[2] "Z-9s" #. ~ Description for {'str': 'Z-9'} #: data/json/monsters/zed-animal.json @@ -128771,9 +129056,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "rot-weiler" msgid_plural "rot-weilers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rot-weiler" +msgstr[1] "rot-weilers" +msgstr[2] "rot-weilers" #. ~ Description for {'str': 'rot-weiler'} #: data/json/monsters/zed-animal.json @@ -128785,9 +129070,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "grim howler" msgid_plural "grim howlers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aullador sombrío" +msgstr[1] "aulladores sombríos" +msgstr[2] "aulladores sombríos" #. ~ Description for {'str': 'grim howler'} #: data/json/monsters/zed-animal.json @@ -128801,9 +129086,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "zombear" msgid_plural "zombears" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "oso zombi" +msgstr[1] "osos zombis" +msgstr[2] "osos zombis" #. ~ Description for {'str': 'zombear'} #: data/json/monsters/zed-animal.json @@ -128817,9 +129102,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "festering boar" msgid_plural "festering boars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "jabalí podrido" +msgstr[1] "jabalís podridos" +msgstr[2] "jabalís podridos" #. ~ Description for {'str': 'festering boar'} #: data/json/monsters/zed-animal.json @@ -128850,9 +129135,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "antlered horror" msgid_plural "antlered horrors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "horror con cuernos" +msgstr[1] "horrores con cuernos" +msgstr[2] "horrores con cuernos" #. ~ Description for {'str': 'antlered horror'} #: data/json/monsters/zed-animal.json @@ -128870,9 +129155,9 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "decayed pouncer" msgid_plural "decayed pouncers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "saltador putrefacto" +msgstr[1] "saltadores putrefactos" +msgstr[2] "saltadores putrefactos" #. ~ Description for {'str': 'decayed pouncer'} #: data/json/monsters/zed-animal.json @@ -128886,9 +129171,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "scarred zombie" msgid_plural "scarred zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi cicatrizado" +msgstr[1] "zombis cicatrizados" +msgstr[2] "zombis cicatrizados" #. ~ Description for {'str': 'scarred zombie'} #: data/json/monsters/zed-classic.json @@ -128897,13 +129182,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -128916,9 +129194,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "zombie cop" msgid_plural "zombie cops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi policía" +msgstr[1] "zombis policías" +msgstr[2] "zombis policías" #. ~ Description for {'str': 'zombie cop'} #: data/json/monsters/zed-classic.json @@ -128931,9 +129209,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "crawling zombie" msgid_plural "crawling zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi arrastrador" +msgstr[1] "zombis arrastradores" +msgstr[2] "zombis arrastradores" #. ~ Description for {'str': 'crawling zombie'} #: data/json/monsters/zed-classic.json @@ -128947,9 +129225,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "zombie dancer" msgid_plural "zombie dancers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi bailarín" +msgstr[1] "zombis bailarines" +msgstr[2] "zombis bailarines" #. ~ Description for {'str': 'zombie dancer'} #: data/json/monsters/zed-classic.json @@ -128971,9 +129249,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "fat zombie" msgid_plural "fat zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi gordo" +msgstr[1] "zombis gordos" +msgstr[2] "zombis gordos" #. ~ Description for {'str': 'fat zombie'} #: data/json/monsters/zed-classic.json @@ -128987,9 +129265,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "firefighter zombie" msgid_plural "firefighter zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi bombero" +msgstr[1] "zombis bomberos" +msgstr[2] "zombis bomberos" #. ~ Description for {'str': 'firefighter zombie'} #: data/json/monsters/zed-classic.json @@ -129004,9 +129282,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "hazmat zombie" msgid_plural "hazmat zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi con materiales peligrosos" +msgstr[1] "zombis con materiales peligrosos" +msgstr[2] "zombis con materiales peligrosos" #. ~ Description for {'str': 'hazmat zombie'} #: data/json/monsters/zed-classic.json @@ -129020,9 +129298,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "decayed zombie" msgid_plural "decayed zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi deteriorado" +msgstr[1] "zombis deteriorados" +msgstr[2] "zombis deteriorados" #. ~ Description for {'str': 'decayed zombie'} #: data/json/monsters/zed-classic.json @@ -129050,9 +129328,9 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "tough zombie" msgid_plural "tough zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi fuerte" +msgstr[1] "zombis fuertes" +msgstr[2] "zombis fuertes" #. ~ Description for {'str': 'tough zombie'} #: data/json/monsters/zed-classic.json @@ -129092,9 +129370,9 @@ msgstr "" #: data/json/monsters/zed_acid.json msgid "acidic zombie" msgid_plural "acidic zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi ácido" +msgstr[1] "zombis ácidos" +msgstr[2] "zombis ácidos" #. ~ Description for {'str': 'acidic zombie'} #: data/json/monsters/zed_acid.json @@ -129109,9 +129387,9 @@ msgstr "" #: data/json/monsters/zed_acid.json msgid "corrosive zombie" msgid_plural "corrosive zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi corrosivo" +msgstr[1] "zombis corrosivos" +msgstr[2] "zombis corrosivos" #. ~ Description for {'str': 'corrosive zombie'} #: data/json/monsters/zed_acid.json @@ -129132,9 +129410,9 @@ msgstr "¡El zombi corrosivo escupe una pegote de ácido!" #: data/json/monsters/zed_acid.json msgid "spitter zombie" msgid_plural "spitter zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi escupidor" +msgstr[1] "zombis escupidores" +msgstr[2] "zombis escupidores" #. ~ Description for {'str': 'spitter zombie'} #: data/json/monsters/zed_acid.json @@ -129184,9 +129462,9 @@ msgstr "" #: data/json/monsters/zed_burned.json msgid "fiend" msgid_plural "fiends" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "diablillo" +msgstr[1] "diablillos" +msgstr[2] "diablillos" #. ~ Description for {'str': 'fiend'} #: data/json/monsters/zed_burned.json @@ -129334,9 +129612,9 @@ msgstr "" #: data/json/monsters/zed_electric.json msgid "shocker brute" msgid_plural "shocker brutes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "shocker bruto" +msgstr[1] "shockers bruto" +msgstr[2] "shockers bruto" #. ~ Description for {'str': 'shocker brute'} #: data/json/monsters/zed_electric.json @@ -129353,9 +129631,9 @@ msgstr "" #: data/mods/CrazyCataclysm/crazy_monsters.json msgid "shocker zombie" msgid_plural "shocker zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi cargado" +msgstr[1] "zombis cargados" +msgstr[2] "zombis cargados" #. ~ Description for {'str': 'shocker zombie'} #: data/json/monsters/zed_electric.json @@ -129402,9 +129680,9 @@ msgstr "" #: data/json/monsters/zed_explosive.json msgid "boomer" msgid_plural "boomers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "boomer" +msgstr[1] "boomers" +msgstr[2] "boomers" #. ~ Description for {'str': 'boomer'} #: data/json/monsters/zed_explosive.json @@ -129447,9 +129725,9 @@ msgstr "" #: data/json/monsters/zed_explosive.json msgid "bloated zombie" msgid_plural "bloated zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi hinchado" +msgstr[1] "zombis hinchados" +msgstr[2] "zombis hinchados" #. ~ Description for {'str': 'bloated zombie'} #: data/json/monsters/zed_explosive.json @@ -129498,9 +129776,9 @@ msgstr "" #: data/json/monsters/zed_fusion.json msgid "crawler" msgid_plural "crawlers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arrastrador" +msgstr[1] "arrastradores" +msgstr[2] "arrastradores" #. ~ Description for {'str': 'crawler'} #: data/json/monsters/zed_fusion.json @@ -129609,9 +129887,9 @@ msgstr "" #: data/json/monsters/zed_lab.json msgid "zombie scientist" msgid_plural "zombie scientists" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "científico zombi" +msgstr[1] "científicos zombis" +msgstr[2] "científicos zombis" #. ~ Description for {'str': 'zombie scientist'} #: data/json/monsters/zed_lab.json @@ -129720,9 +129998,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie brute" msgid_plural "zombie brutes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi bruto" +msgstr[1] "zombis brutos" +msgstr[2] "zombis brutos" #. ~ Description for {'str': 'zombie brute'} #: data/json/monsters/zed_misc.json @@ -129735,9 +130013,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie wrestler" msgid_plural "zombie wrestlers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi luchador" +msgstr[1] "zombis luchadores" +msgstr[2] "zombis luchadores" #. ~ Description for {'str': 'zombie wrestler'} #: data/json/monsters/zed_misc.json @@ -129751,9 +130029,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie nightstalker" msgid_plural "zombie nightstalkers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi acosador nocturno" +msgstr[1] "zombis acosadores nocturnos" +msgstr[2] "zombis acosadores nocturnos" #. ~ Description for {'str': 'zombie nightstalker'} #: data/json/monsters/zed_misc.json @@ -129783,9 +130061,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "grabber zombie" msgid_plural "grabber zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi agarrador" +msgstr[1] "zombis agarradores" +msgstr[2] "zombis agarradores" #. ~ Description for {'str': 'grabber zombie'} #: data/json/monsters/zed_misc.json @@ -129800,9 +130078,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "grappler zombie" msgid_plural "grappler zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi aferrador" +msgstr[1] "zombis aferradores" +msgstr[2] "zombis aferradores" #. ~ Description for {'str': 'grappler zombie'} #: data/json/monsters/zed_misc.json @@ -129841,9 +130119,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie hulk" msgid_plural "zombie hulks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi hulk" +msgstr[1] "zombis hulk" +msgstr[2] "zombis hulk" #. ~ Description for {'str': 'zombie hulk'} #: data/json/monsters/zed_misc.json @@ -129874,9 +130152,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "Thriller" msgid_plural "Thrillers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Thriller" +msgstr[1] "Thrillers" +msgstr[2] "Thrillers" #. ~ Description for {'str': 'Thriller'} #: data/json/monsters/zed_misc.json @@ -129911,9 +130189,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie master" msgid_plural "zombie masters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maestro zombi" +msgstr[1] "maestros zombis" +msgstr[2] "maestros zombis" #. ~ Description for {'str': 'zombie master'} #: data/json/monsters/zed_misc.json @@ -129934,9 +130212,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie necromancer" msgid_plural "zombie necromancers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi nigromante" +msgstr[1] "zombis nigromantes" +msgstr[2] "zombis nigromantes" #. ~ Description for {'str': 'zombie necromancer'} #: data/json/monsters/zed_misc.json @@ -130040,9 +130318,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "shrieker zombie" msgid_plural "shrieker zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi aullador" +msgstr[1] "zombis aulladores" +msgstr[2] "zombis aulladores" #. ~ Description for {'str': 'shrieker zombie'} #: data/json/monsters/zed_misc.json @@ -130056,9 +130334,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "skull zombie" msgid_plural "skull zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi calavera" +msgstr[1] "zombis calavera" +msgstr[2] "zombis calavera" #. ~ Description for {'str': 'skull zombie'} #: data/json/monsters/zed_misc.json @@ -130073,9 +130351,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "smoker zombie" msgid_plural "smoker zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi humeante" +msgstr[1] "zombis humeantes" +msgstr[2] "zombis humeantes" #. ~ Description for {'str': 'smoker zombie'} #: data/json/monsters/zed_misc.json @@ -130089,9 +130367,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "swimmer zombie" msgid_plural "swimmer zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi nadador" +msgstr[1] "zombis nadadores" +msgstr[2] "zombis nadadores" #. ~ Description for {'str': 'swimmer zombie'} #: data/json/monsters/zed_misc.json @@ -130105,9 +130383,9 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie technician" msgid_plural "zombie technicians" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi técnico" +msgstr[1] "zombis técnicos" +msgstr[2] "zombis técnicos" #. ~ Description for {'str': 'zombie technician'} #: data/json/monsters/zed_misc.json @@ -130167,9 +130445,9 @@ msgstr "" #: data/json/monsters/zed_radiation.json msgid "charred nightmare" msgid_plural "charred nightmares" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pesadilla chamuscada" +msgstr[1] "pesadillas chamuscadas" +msgstr[2] "pesadillas chamuscadas" #. ~ Description for {'str': 'charred nightmare'} #: data/json/monsters/zed_radiation.json @@ -130184,9 +130462,9 @@ msgstr "" #: data/json/monsters/zed_radiation.json msgid "irradiated wanderer" msgid_plural "irradiated wanderers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "errante irradiado" +msgstr[1] "errantes irradiados" +msgstr[2] "errantes irradiados" #. ~ Description for {'str': 'irradiated wanderer'} #: data/json/monsters/zed_radiation.json @@ -130201,9 +130479,9 @@ msgstr "" #: data/json/monsters/zed_skeletal.json msgid "skeleton" msgid_plural "skeletons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esqueleto" +msgstr[1] "esqueletos" +msgstr[2] "esqueletos" #. ~ Description for {'str': 'skeleton'} #: data/json/monsters/zed_skeletal.json @@ -130271,9 +130549,9 @@ msgstr "" #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json msgid "zombie soldier" msgid_plural "zombie soldiers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "soldado zombi" +msgstr[1] "soldados zombis" +msgstr[2] "soldados zombis" #. ~ Description for {'str': 'zombie soldier'} #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json @@ -130438,9 +130716,9 @@ msgstr "" #: data/json/monsters/zed_soldiers.json msgid "zombie bio-operator" msgid_plural "zombie bio-operators" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi bio-operador" +msgstr[1] "zombis bio-operador" +msgstr[2] "zombis bio-operador" #. ~ Description for {'str': 'zombie bio-operator'} #: data/json/monsters/zed_soldiers.json @@ -130468,9 +130746,9 @@ msgstr "" #: data/json/monsters/zed_survivor.json msgid "survivor zombie" msgid_plural "survivor zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zombi superviviente" +msgstr[1] "zombis supervivientes" +msgstr[2] "zombis supervivientes" #. ~ Description for {'str': 'survivor zombie'} #: data/json/monsters/zed_survivor.json @@ -139993,7 +140271,8 @@ msgid "I'll kill you if you don't." msgstr "Te voy a matar si no lo hacés." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "Olvidate." @@ -148245,10 +148524,6 @@ msgstr "monstruo" msgid "demon" msgstr "demonio" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "horror" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "bestia indescifrable" @@ -162544,6 +162819,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -162580,6 +162865,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -166492,9 +166791,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "RDX sand bomb" msgid_plural "RDX sand bombs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bomba de RDX y arena" +msgstr[1] "bombas de RDX y arena" +msgstr[2] "bombas de RDX y arena" #. ~ Use action msg for {'str': 'RDX sand bomb'}. #: data/json/obsoletion/items.json @@ -166515,9 +166814,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "active RDX sand bomb" msgid_plural "active RDX sand bombs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bomba encendida de RDX y arena" +msgstr[1] "bombas encendidas de RDX y arena" +msgstr[2] "bombas encendidas de RDX y arena" #. ~ Description for {'str': 'active RDX sand bomb'} #: data/json/obsoletion/items.json @@ -167226,9 +167525,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "plastic fork" msgid_plural "plastic forks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tenedor de plástico" +msgstr[1] "tenedores de plástico" +msgstr[2] "tenedores de plástico" #. ~ Description for {'str': 'plastic fork'} #: data/json/obsoletion/items.json @@ -167242,9 +167541,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "plastic spoon" msgid_plural "plastic spoons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cuchara de plástico" +msgstr[1] "cucharas de plástico" +msgstr[2] "cucharas de plástico" #. ~ Description for {'str': 'plastic spoon'} #: data/json/obsoletion/items.json @@ -167292,9 +167591,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "plastic knife" msgid_plural "plastic knives" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cuchillo de plástico" +msgstr[1] "cuchillos de plástico" +msgstr[2] "cuchillos de plástico" #. ~ Description for {'str': 'plastic knife', 'str_pl': 'plastic knives'} #: data/json/obsoletion/items.json @@ -169464,9 +169763,9 @@ msgstr "¿Ya conseguiste la vacuna para la gripe?" #: data/json/obsoletion/monsters.json msgid "centipede" msgid_plural "centipedes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ciempiés" +msgstr[1] "ciempiés" +msgstr[2] "ciempiés" #. ~ Description for {'str': 'centipede'} #: data/json/obsoletion/monsters.json @@ -169479,9 +169778,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "deer mouse" msgid_plural "deer mouses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arce" +msgstr[1] "arces" +msgstr[2] "arces" #. ~ Description for {'str': 'deer mouse'} #: data/json/obsoletion/monsters.json @@ -169512,9 +169811,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "bull frog" msgid_plural "bull frogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rana toro" +msgstr[1] "ranas toro" +msgstr[2] "ranas toro" #. ~ Description for {'str': 'bull frog'} #: data/json/obsoletion/monsters.json @@ -169528,9 +169827,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "mosquito" msgid_plural "mosquitos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosquito" +msgstr[1] "mosquitos" +msgstr[2] "mosquitos" #. ~ Description for {'str': 'mosquito'} #: data/json/obsoletion/monsters.json @@ -169544,9 +169843,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "shrew" msgid_plural "shrews" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "musaraña" +msgstr[1] "musarañas" +msgstr[2] "musarañas" #. ~ Description for {'str': 'shrew'} #: data/json/obsoletion/monsters.json @@ -169561,9 +169860,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "slug" msgid_plural "slugs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "babosa" +msgstr[1] "babosas" +msgstr[2] "babosas" #. ~ Description for {'str': 'slug'} #: data/json/obsoletion/monsters.json @@ -169579,9 +169878,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "jumping spider" msgid_plural "jumping spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña saltarina" +msgstr[1] "arañas saltarinas" +msgstr[2] "arañas saltarinas" #. ~ Description for {'str': 'jumping spider'} #: data/json/obsoletion/monsters.json @@ -169597,9 +169896,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "trapdoor spider" msgid_plural "trapdoor spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña tapadera" +msgstr[1] "arañas tapadera" +msgstr[2] "arañas tapadera" #. ~ Description for {'str': 'trapdoor spider'} #: data/json/obsoletion/monsters.json @@ -169614,9 +169913,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "black widow spider" msgid_plural "black widow spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "viuda negra" +msgstr[1] "viudas negras" +msgstr[2] "viudas negras" #. ~ Description for {'str': 'black widow spider'} #: data/json/obsoletion/monsters.json @@ -169630,9 +169929,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "wolf spider" msgid_plural "wolf spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "araña lobo" +msgstr[1] "arañas lobo" +msgstr[2] "arañas lobo" #. ~ Description for {'str': 'wolf spider'} #: data/json/obsoletion/monsters.json @@ -169646,9 +169945,9 @@ msgstr "" #: data/json/obsoletion/monsters.json msgid "wasp" msgid_plural "wasps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "avispa" +msgstr[1] "avispas" +msgstr[2] "avispas" #. ~ Description for {'str': 'wasp'} #: data/json/obsoletion/monsters.json @@ -169701,9 +170000,9 @@ msgstr "" #: data/mods/No_Hope/monsters.json msgid "chicken walker" msgid_plural "chicken walkers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mecha-gallina" +msgstr[1] "mecha-gallinas" +msgstr[2] "mecha-gallinas" #. ~ Description for {'str': 'chicken walker'} #. ~ Description for chicken walker @@ -192820,9 +193119,9 @@ msgstr "" #: data/mods/Aftershock/items/items.json msgid "titanium implant" msgid_plural "titanium implants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "implante de titanio" +msgstr[1] "implantes de titanio" +msgstr[2] "implantes de titanio" #. ~ Description for {'str': 'titanium implant'} #: data/mods/Aftershock/items/items.json @@ -192837,9 +193136,9 @@ msgstr "" #: data/mods/Aftershock/items/items.json msgid "titanium tooth" msgid_plural "titanium tooths" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "diente de titanio" +msgstr[1] "dientes de titanio" +msgstr[2] "dientes de titanio" #. ~ Description for {'str': 'titanium tooth'} #: data/mods/Aftershock/items/items.json @@ -195088,6 +195387,14 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -195172,9 +195479,9 @@ msgstr "" #: data/mods/Aftershock/mobs/zombies.json msgid "headless horror" msgid_plural "headless horrors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "horror decapitado" +msgstr[1] "horrores decapitados" +msgstr[2] "horrores decapitados" #. ~ Description for {'str': 'headless horror'} #: data/mods/Aftershock/mobs/zombies.json @@ -205377,6 +205684,14 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -217501,16 +217816,16 @@ msgstr "" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "HK417 magazine" msgid_plural "HK417 magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador HK417" +msgstr[1] "cargadores HK417" +msgstr[2] "cargadores HK417" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "HK417 compact magazine" msgid_plural "HK417 compact magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cargador compacto HK417" +msgstr[1] "cargadores compacto HK417" +msgstr[2] "cargadores compacto HK417" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "HK417 makeshift magazine" @@ -218313,6 +218628,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -218448,6 +218768,27 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -222478,16 +222819,16 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "cudgel +1" msgid_plural "cudgel +1s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "garrote +1s" +msgstr[1] "garrotes +1s" +msgstr[2] "garrotes +1s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "cudgel +2" msgid_plural "cudgel +2s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "garrote +2s" +msgstr[1] "garrotes +2s" +msgstr[2] "garrotes +2s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "quarterstaff +1" @@ -222520,58 +222861,72 @@ msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "longsword +1" msgid_plural "longsword +1s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espada larga +1s" +msgstr[1] "espadas largas +1s" +msgstr[2] "espadas largas +1s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "longsword +2" msgid_plural "longsword +2s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espadas largas +1s" +msgstr[1] "espadas largas +2s" +msgstr[2] "espadas largas +2s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "sledge hammer +1" msgid_plural "sledge hammer +1s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maza +1s" +msgstr[1] "mazas +1s" +msgstr[2] "mazas +1s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "sledge hammer +2" msgid_plural "sledge hammer +2s" +msgstr[0] "maza +2s" +msgstr[1] "mazas +2s" +msgstr[2] "mazas +2s" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" msgstr[0] "" msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json -msgid "warhammer +1" -msgid_plural "warhammer +1s" +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "warhammer +1" +msgid_plural "warhammer +1s" +msgstr[0] "martillo de guerra +1s" +msgstr[1] "martillos de guerra +1s" +msgstr[2] "martillos de guerra +1s" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +2" msgid_plural "warhammer +2s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "martillo de guerra +2s" +msgstr[1] "martillos de guerra +2s" +msgstr[2] "martillos de guerra +2s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "bat +1" msgid_plural "bat +1s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bate +1s" +msgstr[1] "bates +1s" +msgstr[2] "bates +1s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "bat +2" msgid_plural "bat +2s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bate +2s" +msgstr[1] "bates +2s" +msgstr[2] "bates +2s" #: data/mods/Magiclysm/items/enchanted_melee.json msgid "aluminum bat +1" @@ -222784,6 +223139,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -222791,6 +223147,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -222854,6 +223211,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -222861,6 +223219,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -223063,6 +223422,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -223716,9 +224089,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_rings.json msgid "ring of protection +2" msgid_plural "rings of protection +2" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de protección +2" +msgstr[1] "anillos de protección +2" +msgstr[2] "anillos de protección +2" #. ~ Description for {'str': 'ring of protection +2', 'str_pl': 'rings of #. protection +2'} @@ -223731,9 +224104,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_rings.json msgid "ring of protection +4" msgid_plural "rings of protection +4" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de protección +4" +msgstr[1] "anillos de protección +4" +msgstr[2] "anillos de protección +4" #. ~ Description for {'str': 'ring of protection +4', 'str_pl': 'rings of #. protection +4'} @@ -223746,9 +224119,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_rings.json msgid "ring of protection +6" msgid_plural "rings of protection +6" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de protección +6" +msgstr[1] "anillos de protección +6" +msgstr[2] "anillos de protección +6" #. ~ Description for {'str': 'ring of protection +6', 'str_pl': 'rings of #. protection +6'} @@ -223761,9 +224134,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_rings.json msgid "ring of protection +8" msgid_plural "rings of protection +8" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de protección +8" +msgstr[1] "anillos de protección +8" +msgstr[2] "anillos de protección +8" #. ~ Description for {'str': 'ring of protection +8', 'str_pl': 'rings of #. protection +8'} @@ -223776,9 +224149,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_tokens.json msgid "magic token" msgid_plural "magic tokens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "token mágico" +msgstr[1] "tokens mágicos" +msgstr[2] "tokens mágicos" #: data/mods/Magiclysm/items/enchanted_tokens.json msgid "longsword token" @@ -224011,6 +224384,90 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -225230,6 +225687,21 @@ msgstr "" "fuego de un dragón en la tapa. Adentro, tiene muchas maneras de convertir la" " piel y el pellejo de un monstruo en equipo de protección." +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -225334,9 +225806,9 @@ msgstr[2] "" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Summon Skeleton" msgid_plural "Scrolls of Summon Skeleton" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Pergamino para Invocar Esqueleto" +msgstr[1] "Pergaminos para Invocar Esqueletos" +msgstr[2] "Pergaminos para Invocar Esqueletos" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Summon Floating Disk" @@ -226434,6 +226906,13 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -226450,13 +226929,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -229630,10 +230102,24 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -232142,6 +232628,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -232164,6 +232659,79 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -233687,6 +234255,14 @@ msgstr "Act./Desact. Modo Debug" msgid "Debug Menu" msgstr "Modo Debug" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Ver Mapa de Olor" @@ -234242,6 +234818,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -234400,7 +234996,31 @@ msgstr "Establecer modos de torreta" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -240134,6 +240754,30 @@ msgstr "abcdefghijklmnopqrstuvwxyz" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -245048,6 +245692,10 @@ msgstr "Información..." msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -245164,6 +245812,10 @@ msgstr "Salir a menú principal" msgid "Player…" msgstr "Jugador..." +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -246037,6 +246689,10 @@ msgstr "Ahí no hay un vehículo." msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -258661,6 +259317,11 @@ msgstr "¡Te sacan el/a %s de la mano!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "Intentás darle al/a %s de comer un poco de %s, ¡pero desaparece!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "Querés darle la comida para perros, pero ¡te muerde los dedos!" @@ -264623,6 +265284,11 @@ msgstr "" msgid "Create World" msgstr "Crear Mundo" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "¿Bugs? ¿Sugerencias? Usá los links en MOTD para reportarlos." @@ -264893,6 +265559,13 @@ msgstr "¿Seguro que querés borrar %s?" msgid "Sorry, something went wrong." msgstr "Perdón, algo no funcionó." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -268647,6 +269320,15 @@ msgstr[2] "" msgid "Mod version" msgstr "Versión de Mod" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -271666,13 +272348,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "Enfocar las tendencias hacia:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "humano" -msgstr[1] "humanos" -msgstr[2] "humanos" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -274323,6 +274998,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "General" @@ -275534,6 +276217,16 @@ msgstr "" "Es la cantidad de tiempo que dura la pausa entre los frames de una " "animación, medido en ms." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -275613,64 +276306,77 @@ msgid "Font height" msgstr "Altura de fuente de texto" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" +"Establece la altura de la fuente de texto. Requiere reiniciar el juego." #: src/options.cpp msgid "Font size" msgstr "Tamaño de fuente de texto" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "" +msgid "Set the font size. Requires restart." +msgstr "Establece el tamaño de fuente de texto. Requiere reiniciar el juego." #: src/options.cpp msgid "Map font width" msgstr "Anchura de fuente de texto del mapa" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" +"Establece la anchura de la fuente de texto del mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Map font height" msgstr "Altura de fuente de texto del mapa" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" +"Establece la altura de la fuente de texto del mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Map font size" msgstr "Tamaño de fuente de texto del mapa" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" +"Establece el tamaño de fuente de texto del mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Overmap font width" msgstr "Anchura de fuente de texto sobre el mapa" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" +"Establece la anchura de la fuente de texto sobre el mapa. Requiere reiniciar" +" el juego." #: src/options.cpp msgid "Overmap font height" msgstr "Altura de fuente de texto sobre el mapa" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" +"Establece la altura de la fuente de texto sobre el mapa. Requiere reiniciar " +"el juego." #: src/options.cpp msgid "Overmap font size" msgstr "Tamaño de fuente de texto sobre el mapa" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" +"Establece el tamaño de fuente de texto sobre el mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -283479,6 +284185,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "N/D" diff --git a/lang/po/es_ES.po b/lang/po/es_ES.po index 5ebe4ec99a5b..12ac6a37fedd 100644 --- a/lang/po/es_ES.po +++ b/lang/po/es_ES.po @@ -1,12 +1,12 @@ # # Translators: -# Jean Germain , 2022 +# Jean Germain , 2023 # Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Coolthulhu , 2023\n" "Language-Team: Spanish (Spain) (https://app.transifex.com/bn-team/teams/113585/es_ES/)\n" "MIME-Version: 1.0\n" @@ -2247,10 +2247,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3128,9 +3136,9 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "Squeaky Ankles" msgid_plural "Squeaky Ankles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Tobillos Chillones" +msgstr[1] "Tobillos Chillones" +msgstr[2] "Tobillos Chillones" #. ~ Description for {'str': 'Squeaky Ankles'} #: data/json/bionics.json @@ -3528,9 +3536,9 @@ msgstr "" #: data/json/bionics.json data/json/items/gun/bio.json msgid "EMP Projector" msgid_plural "EMP Projectors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "proyector PEM" +msgstr[1] "proyectores PEM" +msgstr[2] "proyectores PEM" #. ~ Description for {'str': 'EMP Projector'} #: data/json/bionics.json @@ -3681,9 +3689,9 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "Glowy Thing" msgid_plural "Glowy Things" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cosa Brillante" +msgstr[1] "Cosas Brillantes" +msgstr[2] "Cosas Brillantes" #. ~ Description for {'str': 'Glowy Thing'} #: data/json/bionics.json @@ -4379,9 +4387,9 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "Wire-Induced Stiffness" msgid_plural "Wire-Induced Stiffnesses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Rigidez Inducida por Cable" +msgstr[1] "Rigidez Inducida por Cable" +msgstr[2] "Rigidez Inducida por Cable" #. ~ Description for {'str': 'Wire-Induced Stiffness'} #: data/json/bionics.json @@ -4466,9 +4474,9 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "Self-Locking Thumbs" msgid_plural "Self-Locking Thumbs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Pulgares Auto-Trabables" +msgstr[1] "Pulgares Auto-Trabables" +msgstr[2] "Pulgares Auto-Trabables" #. ~ Description for {'str': 'Self-Locking Thumbs'} #: data/json/bionics.json @@ -4632,9 +4640,9 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "Gasoline Fuel Cell CBM" msgid_plural "Gasoline Fuel Cell CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Celda de Nafta" +msgstr[1] "MCB Celda de Nafta" +msgstr[2] "MCB Celda de Nafta" #. ~ Description for {'str': 'Gasoline Fuel Cell CBM'} #: data/json/bionics.json @@ -4831,10 +4839,25 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "apéndice" @@ -9172,6 +9195,17 @@ msgstr "" msgid "You're winded." msgstr "Te falta el aire." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "¡El techo se te cae encima!" @@ -24319,38 +24353,102 @@ msgstr "arma" #: data/json/items/book/maps.json data/json/items/tool/deployable.json msgid "seeing this is a bug" msgid_plural "seeing this is a bug" +msgstr[0] "si ves esto es un bug" +msgstr[1] "si ves esto es un bug" +msgstr[2] "si ves esto es un bug" + +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" msgstr[0] "" msgstr[1] "" msgstr[2] "" +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "masa" +msgstr[1] "masas" +msgstr[2] "masas" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -24359,30 +24457,86 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "un hongo" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "un insecto" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -24391,6 +24545,15 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "zombi" +msgstr[1] "zombis" +msgstr[2] "zombis" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "un zombi" @@ -24399,6 +24562,14 @@ msgstr "un zombi" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -24407,18 +24578,56 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "una aberración" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "humano" +msgstr[1] "humanos" +msgstr[2] "humanos" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -28653,9 +28862,9 @@ msgstr "" #: src/magic.cpp src/map_extras.cpp src/recipe.cpp msgid "none" msgid_plural "none" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nada" +msgstr[1] "nada" +msgstr[2] "nada" #: data/json/traps.json data/json/items/tool/traps.json msgid "bubble wrap" @@ -29543,9 +29752,9 @@ msgstr "" #: data/json/vehicleparts/vehicle_parts.json msgid "washing machine" msgid_plural "washing machines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lavarropas" +msgstr[1] "lavarropas" +msgstr[2] "lavarropas" #. ~ Description for washing machine #: data/json/furniture_and_terrain/furniture-appliances.json @@ -30110,9 +30319,9 @@ msgstr "" #: data/json/vehicleparts/vehicle_parts.json msgid "minifreezer" msgid_plural "minifreezers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "minifreezer" +msgstr[1] "minifreezers" +msgstr[2] "minifreezers" #: data/json/furniture_and_terrain/furniture-appliances.json msgid "Switch off the minifreezer." @@ -30817,9 +31026,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "tulip" msgid_plural "tulips" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tulipán" +msgstr[1] "tulipanes" +msgstr[2] "tulipanes" #. ~ Description for tulip #: data/json/furniture_and_terrain/furniture-flora.json @@ -30850,9 +31059,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "black eyed susan" msgid_plural "black eyed susans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rudbeckia" +msgstr[1] "rudbeckias" +msgstr[2] "rudbeckias" #. ~ Description for black eyed susan #: data/json/furniture_and_terrain/furniture-flora.json @@ -30865,9 +31074,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "lily" msgid_plural "lilies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lirio" +msgstr[1] "lirios" +msgstr[2] "lirios" #. ~ Description for lily #: data/json/furniture_and_terrain/furniture-flora.json @@ -30878,9 +31087,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "lotus" msgid_plural "lotuses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lotus" +msgstr[1] "lotus" +msgstr[2] "lotus" #. ~ Description for lotus #. ~ Description for {'str': 'lotus flower'} @@ -30950,9 +31159,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "chicory" msgid_plural "chicory" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "achicoria" +msgstr[1] "achicoria" +msgstr[2] "achicoria" #. ~ Description for chicory #: data/json/furniture_and_terrain/furniture-flora.json @@ -32261,9 +32470,9 @@ msgstr "¿Qué habrá adentro? ¡Vamos a ver!" #: data/json/items/containers.json msgid "large cardboard box" msgid_plural "large cardboard boxes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caja grande de cartón" +msgstr[1] "cajas grandes de cartón" +msgstr[2] "cajas grandes de cartón" #. ~ Description for large cardboard box #: data/json/furniture_and_terrain/furniture-storage.json @@ -32588,9 +32797,9 @@ msgstr "" #: data/json/vehicleparts/vehicle_parts.json msgid "workbench" msgid_plural "workbenches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mesa de trabajo" +msgstr[1] "mesas de trabajo" +msgstr[2] "mesas de trabajo" #. ~ Description for workbench #. ~ Description for {'str': 'workbench', 'str_pl': 'workbenches'} @@ -32663,9 +32872,9 @@ msgstr "" #: data/json/items/tool/deployable.json msgid "tourist table" msgid_plural "tourist tables" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mesa de turista" +msgstr[1] "mesas de turista" +msgstr[2] "mesas de turista" #. ~ Description for tourist table #: data/json/furniture_and_terrain/furniture-surfaces.json @@ -33338,9 +33547,9 @@ msgstr "" #: data/json/items/tool/deployable.json msgid "metal butchering rack" msgid_plural "metal butchering racks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "soporte de metal para carnear" +msgstr[1] "soportes de metal para carnear" +msgstr[2] "soportes de metal para carnear" #. ~ Description for metal butchering rack #: data/json/furniture_and_terrain/furniture-tools.json @@ -35993,9 +36202,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "underbrush" msgid_plural "underbrushes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "underbrush" +msgstr[1] "malezas" +msgstr[2] "malezas" #. ~ Description for underbrush #: data/json/furniture_and_terrain/terrain-flora.json @@ -36229,9 +36438,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "grass" msgid_plural "grasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pasto" +msgstr[1] "pastos" +msgstr[2] "pastos" #. ~ Description for grass #: data/json/furniture_and_terrain/terrain-flora.json @@ -37548,9 +37757,9 @@ msgstr "" #: data/json/items/generic.json msgid "small railroad track" msgid_plural "small railroad tracks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vía pequeña" +msgstr[1] "vías pequeñas" +msgstr[2] "vías pequeñas" #. ~ Description for small railroad track #: data/json/furniture_and_terrain/terrain-railroads.json @@ -39865,9 +40074,9 @@ msgstr "" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "plutonium slurry" msgid_plural "plutonium slurry" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulpa de plutonio" +msgstr[1] "pulpa de plutonio" +msgstr[2] "pulpa de plutonio" #. ~ Description for {'str_sp': 'plutonium slurry'} #. ~ Description for {'str_sp': 'watery plutonium slurry'} @@ -39881,9 +40090,9 @@ msgstr "" #: data/json/items/ammo.json msgid "watery plutonium slurry" msgid_plural "watery plutonium slurry" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulpa acuosa de plutonio" +msgstr[1] "pulpa acuosa de plutonio" +msgstr[2] "pulpa acuosa de plutonio" #: data/json/items/ammo.json data/json/snippets/music.json msgid "rock" @@ -39918,9 +40127,9 @@ msgstr "" #: data/json/items/ammo.json msgid "clay pellet" msgid_plural "clay pellets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolita de arcilla" +msgstr[1] "bolitas de arcilla" +msgstr[2] "bolitas de arcilla" #. ~ Description for {'str': 'clay pellet'} #: data/json/items/ammo.json @@ -40014,9 +40223,9 @@ msgstr "" #: data/json/items/ammo.json msgid "hydrogen canister" msgid_plural "hydrogen canisters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata de hidrógeno" +msgstr[1] "latas de hidrógeno" +msgstr[2] "latas de hidrógeno" #. ~ Description for {'str': 'hydrogen canister'} #: data/json/items/ammo.json @@ -40043,9 +40252,9 @@ msgstr "" #: data/json/items/ammo.json msgid "oxidizer powder" msgid_plural "oxidizer powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "polvo oxidante" +msgstr[1] "polvo oxidante" +msgstr[2] "polvo oxidante" #. ~ Description for {'str': 'oxidizer powder'} #: data/json/items/ammo.json @@ -40055,9 +40264,9 @@ msgstr "Polvo volátil de oxidante químico." #: data/json/items/ammo.json msgid "lye powder" msgid_plural "lye powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "polvo de lejía" +msgstr[1] "polvo de lejía" +msgstr[2] "polvo de lejía" #. ~ Description for {'str': 'lye powder'} #: data/json/items/ammo.json @@ -40143,9 +40352,9 @@ msgstr "" #: data/json/items/ammo.json msgid "chunk of rubber" msgid_plural "chunks of rubber" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de goma" +msgstr[1] "pedazos de goma" +msgstr[2] "pedazos de goma" #. ~ Description for {'str': 'chunk of rubber', 'str_pl': 'chunks of rubber'} #: data/json/items/ammo.json @@ -40183,9 +40392,9 @@ msgstr "Un rollo de cinta médica, parecida a la cinta adhesiva." #: data/json/items/ammo.json msgid "placeholder ammunition" msgid_plural "placeholder ammunitions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de referencia" +msgstr[1] "municiones de referencia" +msgstr[2] "municiones de referencia" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "charcoal" @@ -40209,9 +40418,9 @@ msgstr "" #: data/json/items/ammo.json msgid "calcium carbide premix" msgid_plural "calcium carbide premix" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "premezcla de carburo de calcio" +msgstr[1] "premezcla de carburo de calcio" +msgstr[2] "premezcla de carburo de calcio" #. ~ Description for {'str_sp': 'calcium carbide premix'} #: data/json/items/ammo.json @@ -40225,9 +40434,9 @@ msgstr "" #: data/json/items/ammo.json msgid "coal" msgid_plural "coals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carbón" +msgstr[1] "carbón" +msgstr[2] "carbón" #. ~ Description for {'str': 'coal'} #: data/json/items/ammo.json @@ -40259,9 +40468,9 @@ msgstr "" #: data/json/items/ammo.json msgid "RA10K stimulant module" msgid_plural "RA10K stimulant modules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "módulo estimulante RA10K" +msgstr[1] "módulos estimulantes RA10K" +msgstr[2] "módulos estimulantes RA10K" #. ~ Description for {'str': 'RA10K stimulant module'} #: data/json/items/ammo.json @@ -40289,9 +40498,9 @@ msgstr "Un cartucho de filtros de repuesto para el rebreather." #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "filter mask cartridge" msgid_plural "filter mask cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de barbijo" +msgstr[1] "cartuchos de barbijo" +msgstr[2] "cartuchos de barbijo" #. ~ Description for {'str': 'filter mask cartridge'} #: data/json/items/ammo.json @@ -40303,9 +40512,9 @@ msgstr "" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "gas mask cartridge" msgid_plural "gas mask cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de máscara de gas" +msgstr[1] "cartuchos de máscara de gas" +msgstr[2] "cartuchos de máscara de gas" #. ~ Description for {'str': 'gas mask cartridge'} #: data/json/items/ammo.json @@ -40316,9 +40525,9 @@ msgstr "" #: data/json/items/ammo.json msgid "chemical mask cartridge" msgid_plural "chemical mask cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de máscara química" +msgstr[1] "cartuchos de máscara química" +msgstr[2] "cartuchos de máscara química" #. ~ Description for {'str': 'chemical mask cartridge'} #: data/json/items/ammo.json @@ -40345,9 +40554,9 @@ msgstr "" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "fish bait" msgid_plural "fish baits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carnada" +msgstr[1] "carnadas" +msgstr[2] "carnadas" #. ~ Description for {'str': 'fish bait'} #: data/json/items/ammo.json @@ -40357,9 +40566,9 @@ msgstr "Un cebo utilizado en trampas para atraer a los peces." #: data/json/items/ammo.json msgid "spiked homemade rocket" msgid_plural "spiked homemade rockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil casero con espiga" +msgstr[1] "misiles caseros con espiga" +msgstr[2] "misiles caseros con espiga" #. ~ Description for {'str': 'spiked homemade rocket'} #: data/json/items/ammo.json @@ -40376,9 +40585,9 @@ msgstr "" #: data/json/items/ammo.json msgid "explosive homemade rocket" msgid_plural "explosive homemade rockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil casero explosivo" +msgstr[1] "misiles caseros explosivos" +msgstr[2] "misiles caseros explosivos" #. ~ Description for {'str': 'explosive homemade rocket'} #: data/json/items/ammo.json @@ -40394,9 +40603,9 @@ msgstr "" #: data/json/items/ammo.json msgid "incendiary homemade rocket" msgid_plural "incendiary homemade rockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil casero incendiario" +msgstr[1] "misiles caseros incendiarios" +msgstr[2] "misiles caseros incendiarios" #. ~ Description for {'str': 'incendiary homemade rocket'} #: data/json/items/ammo.json @@ -40428,9 +40637,9 @@ msgstr "" #: data/json/items/ammo.json msgid "unfinished calcium carbide" msgid_plural "unfinished calcium carbide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carburo de calcio inconcluso" +msgstr[1] "carburo de calcio inconcluso" +msgstr[2] "carburo de calcio inconcluso" #. ~ Description for {'str_sp': 'unfinished calcium carbide'} #: data/json/items/ammo.json @@ -40444,9 +40653,9 @@ msgstr "" #: data/json/items/ammo.json msgid "chain link" msgid_plural "chain links" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "eslabón" +msgstr[1] "eslabones" +msgstr[2] "eslabones" #. ~ Description for {'str': 'chain link'} #: data/json/items/ammo.json @@ -40601,9 +40810,9 @@ msgstr "disparos de .410" #: data/mods/Generic_Guns/firearms/black_powder.json msgid "blunderbuss" msgid_plural "blunderbusses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trabuco" +msgstr[1] "trabucos" +msgstr[2] "trabucos" #: data/json/items/ammo_types.json #: data/mods/Generic_Guns/gg_ammunition_types.json @@ -40637,9 +40846,9 @@ msgstr ".38" #: data/json/items/ammo_types.json data/json/items/ammo/38super.json msgid ".38 Super" msgid_plural ".38 Supers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 Super" +msgstr[1] ".38 Super" +msgstr[2] ".38 Super" #: data/json/items/ammo_types.json msgid ".40" @@ -40709,16 +40918,16 @@ msgstr "" #: data/json/items/ammo_types.json data/json/items/ammo/40x46mm.json msgid "40x46mm grenade" msgid_plural "40x46mm grenades" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "granada 40x46mm" +msgstr[1] "granadas 40x46mm" +msgstr[2] "granadas 40x46mm" #: data/json/items/ammo_types.json data/json/items/ammo/40x53mm.json msgid "40x53mm grenade" msgid_plural "40x53mm grenades" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "granada 40x53mm" +msgstr[1] "granadas 40x53mm" +msgstr[2] "granadas 40x53mm" #: data/json/items/ammo_types.json msgid "high-explosive anti-tank warhead" @@ -40772,9 +40981,9 @@ msgstr[2] "aceites de motor" #: data/json/items/chemicals_and_resources.json msgid "anesthetic" msgid_plural "anesthetics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anestesia" +msgstr[1] "anestesia" +msgstr[2] "anestesia" #: data/json/items/ammo_types.json msgid "soap" @@ -40944,16 +41153,16 @@ msgstr[2] "leche" #: data/json/items/ammo_types.json data/json/items/comestibles/dairy.json msgid "raw milk" msgid_plural "raw milk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche sin pasteurizar" +msgstr[1] "leche sin pasteurizar" +msgstr[2] "leche sin pasteurizar" #: data/json/items/ammo_types.json data/json/items/ammo/paintball.json msgid "paintball" msgid_plural "paintballs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bola de paintball" +msgstr[1] "bolas de paintball" +msgstr[2] "bolas de paintball" #: data/json/items/ammo_types.json msgid "compressed air" @@ -40970,9 +41179,9 @@ msgstr[2] "hexamina" #: data/json/items/ammo_types.json data/json/items/ammo/300blk.json msgid ".300 AAC Blackout" msgid_plural ".300 AAC Blackouts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".300 AAC Blackout" +msgstr[1] ".300 AAC Blackout" +msgstr[2] ".300 AAC Blackout" #: data/json/items/ammo_types.json data/json/items/comestibles/drink.json msgid "water" @@ -41060,9 +41269,9 @@ msgstr "" #: data/json/items/battery.json msgid "test battery" msgid_plural "test batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "batería de prueba" +msgstr[1] "baterías de prueba" +msgstr[2] "baterías de prueba" #. ~ Description for {'str': 'test battery', 'str_pl': 'test batteries'} #: data/json/items/battery.json @@ -41348,16 +41557,16 @@ msgstr[2] "módulos biónicos abstractos" #: data/json/items/bionics.json msgid "abstract bionic module (npc usable)" msgid_plural "abstract bionic modules (npc usable)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "módulo biónico abstracto (usable por PNJ)" +msgstr[1] "módulos biónicos abstractos (usables por PNJ)" +msgstr[2] "módulos biónicos abstractos (usables por PNJ)" #: data/json/items/bionics.json msgid "abstract faulty bionic module" msgid_plural "abstract faulty bionic modules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "módulo biónico abstracto defectuoso" +msgstr[1] "módulos biónicos abstractos defectuosos" +msgstr[2] "módulos biónicos abstractos defectuosos" #. ~ Description for {'str': 'abstract faulty bionic module'} #: data/json/items/bionics.json @@ -41521,9 +41730,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Shotgun Arm CBM" msgid_plural "Shotgun Arm CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Brazo Escopeta" +msgstr[1] "MCB Brazo Escopeta" +msgstr[2] "MCB Brazo Escopeta" #. ~ Description for {'str': 'Shotgun Arm CBM'} #: data/json/items/bionics.json @@ -41960,9 +42169,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Respirator CBM" msgid_plural "Respirator CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Respirador" +msgstr[1] "MCB Respirador" +msgstr[2] "MCB Respirador" #. ~ Description for {'str': 'Respirator CBM'} #: data/json/items/bionics.json @@ -42121,9 +42330,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Finger Lighter CBM" msgid_plural "Finger Lighter CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Dedo Encendedor" +msgstr[1] "MCB Dedo Encendedor" +msgstr[2] "MCB Dedo Encendedor" #. ~ Description for {'str': 'Finger Lighter CBM'} #: data/json/items/bionics.json @@ -42383,9 +42592,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Power Storage CBM Mk. II" msgid_plural "Power Storage CBM Mk. II" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Almacenamiento de energía Mk. II" +msgstr[1] "MCB Almacenamiento de energía Mk. II" +msgstr[2] "MCB Almacenamiento de energía Mk. II" #. ~ Description for {'str_sp': 'Power Storage CBM Mk. II'} #: data/json/items/bionics.json @@ -42687,9 +42896,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Autonomous Surgical Scalpels CBM" msgid_plural "Autonomous Surgical Scalpels CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Escalpelo Quirúrgico Autónomo" +msgstr[1] "MCB Escalpelos Quirúrgicos Autónomos" +msgstr[2] "MCB Escalpelos Quirúrgicos Autónomos" #. ~ Description for {'str': 'Autonomous Surgical Scalpels CBM'} #: data/json/items/bionics.json @@ -42815,9 +43024,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Joint Servo CBM" msgid_plural "Joint Servo CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Articulaciones Servo" +msgstr[1] "MCB Articulaciones Servo" +msgstr[2] "MCB Articulaciones Servo" #. ~ Description for {'str': 'Joint Servo CBM'} #: data/json/items/bionics.json @@ -42905,9 +43114,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Intravenous Needletip CBM" msgid_plural "Intravenous Needletip CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB de Aguja Intravenosa" +msgstr[1] "MCB de Aguja Intravenosa" +msgstr[2] "MCB de Aguja Intravenosa" #. ~ Description for {'str': 'Intravenous Needletip CBM'} #: data/json/items/bionics.json @@ -42962,9 +43171,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Taste Modifier CBM" msgid_plural "Taste Modifier CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Modificador de Gusto" +msgstr[1] "MCB Modificador de Gusto" +msgstr[2] "MCB Modificador de Gusto" #. ~ Description for {'str': 'Taste Modifier CBM'} #: data/json/items/bionics.json @@ -42980,9 +43189,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Soporific Induction CBM" msgid_plural "Soporific Induction CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Inducción Soporífera" +msgstr[1] "MCB Inducción Soporífera" +msgstr[2] "MCB Inducción Soporífera" #. ~ Description for {'str': 'Soporific Induction CBM'} #: data/json/items/bionics.json @@ -43183,9 +43392,9 @@ msgstr[2] "MCBs Lanzagranadas desplegable" #: data/json/items/bionics.json msgid "Linguistic Coprocessor CBM" msgid_plural "Linguistic Coprocessor CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Coprocesador Lingüístico" +msgstr[1] "MCB Coprocesador Lingüístico" +msgstr[2] "MCB Coprocesador Lingüístico" #. ~ Description for {'str': 'Linguistic Coprocessor CBM'} #: data/json/items/bionics.json @@ -43201,9 +43410,9 @@ msgstr "" #: data/json/items/bionics.json msgid "Dopamine Stimulators CBM" msgid_plural "Dopamine Stimulators CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Simulador de Dopamina" +msgstr[1] "MCB Simulador de Dopamina" +msgstr[2] "MCB Simulador de Dopamina" #. ~ Description for {'str': 'Dopamine Stimulators CBM'} #: data/json/items/bionics.json @@ -43242,9 +43451,9 @@ msgstr[2] "" #: data/json/items/biosignatures.json msgid "bird litter" msgid_plural "bird litter" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "basura de pájaro" +msgstr[1] "basura de pájaro" +msgstr[2] "basura de pájaro" #. ~ Description for {'str_sp': 'bird litter'} #: data/json/items/biosignatures.json @@ -43254,9 +43463,9 @@ msgstr "Son cagadas, plumas y pedazos mugre de pájaro." #: data/json/items/biosignatures.json msgid "cow pie" msgid_plural "cow pies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torta de vaca" +msgstr[1] "tortas de vaca" +msgstr[2] "tortas de vaca" #. ~ Description for cow pie #: data/json/items/biosignatures.json @@ -43268,9 +43477,9 @@ msgstr "" #: data/json/items/biosignatures.json msgid "dog dung" msgid_plural "dog dungs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sorete de perro" +msgstr[1] "soretes de perro" +msgstr[2] "soretes de perro" #. ~ Description for dog dung #: data/json/items/biosignatures.json @@ -43280,9 +43489,9 @@ msgstr "Son las deposiciones de un canino." #: data/json/items/biosignatures.json msgid "manure" msgid_plural "manures" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bosta" +msgstr[1] "bostas" +msgstr[2] "bostas" #. ~ Description for manure #: data/json/items/biosignatures.json @@ -43293,9 +43502,9 @@ msgstr "" #: data/json/items/biosignatures.json msgid "roach dirt" msgid_plural "roach dirts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mugre de cucaracha" +msgstr[1] "mugres de cucaracha" +msgstr[2] "mugres de cucaracha" #. ~ Description for roach dirt #: data/json/items/biosignatures.json @@ -43305,9 +43514,9 @@ msgstr "Son bolitas grandes y negras de materia en descomposición." #: data/json/items/biosignatures.json msgid "fetid goop" msgid_plural "fetid goops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pegote fétido" +msgstr[1] "pegotes fétidos" +msgstr[2] "pegotes fétidos" #. ~ Description for {'str': 'fetid goop'} #: data/json/items/biosignatures.json @@ -43477,9 +43686,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "rhodonite" msgid_plural "rhodonite" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rodonita" +msgstr[1] "rodonita" +msgstr[2] "rodonita" #. ~ Description for {'str_sp': 'rhodonite'} #: data/json/items/chemicals_and_resources.json @@ -43493,9 +43702,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "zincite" msgid_plural "zincite" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zincita" +msgstr[1] "zincita" +msgstr[2] "zincita" #. ~ Description for {'str_sp': 'zincite'} #: data/json/items/chemicals_and_resources.json @@ -43581,9 +43790,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "insecticide" msgid_plural "insecticide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "insecticida" +msgstr[1] "insecticida" +msgstr[2] "insecticida" #. ~ Description for {'str_sp': 'insecticide'} #: data/json/items/chemicals_and_resources.json @@ -43609,9 +43818,9 @@ msgstr "Es agua con sal añadida. No sirve para beber." #: data/json/items/chemicals_and_resources.json msgid "soapy water" msgid_plural "soapy water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "agua jabonosa" +msgstr[1] "agua jabonosa" +msgstr[2] "agua jabonosa" #. ~ Description for {'str_sp': 'soapy water'} #: data/json/items/chemicals_and_resources.json @@ -43731,9 +43940,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "potassium chloride" msgid_plural "potassium chloride" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cloruro de potasio" +msgstr[1] "cloruro de potasio" +msgstr[2] "cloruro de potasio" #. ~ Description for {'str_sp': 'potassium chloride'} #: data/json/items/chemicals_and_resources.json @@ -43789,9 +43998,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "hydrochloric acid" msgid_plural "hydrochloric acid" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ácido hidroclórico" +msgstr[1] "ácido hidroclórico" +msgstr[2] "ácido hidroclórico" #. ~ Description for {'str_sp': 'hydrochloric acid'} #: data/json/items/chemicals_and_resources.json @@ -43929,9 +44138,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "ammonium nitrate pellets" msgid_plural "ammonium nitrate pellets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gránulos de nitrato de amonio" +msgstr[1] "gránulos de nitrato de amonio" +msgstr[2] "gránulos de nitrato de amonio" #. ~ Description for {'str_sp': 'ammonium nitrate pellets'} #: data/json/items/chemicals_and_resources.json @@ -44108,9 +44317,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "match head powder" msgid_plural "match head powder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "polvo de fósforo" +msgstr[1] "polvo de fósforo" +msgstr[2] "polvo de fósforo" #. ~ Description for {'str_sp': 'match head powder'} #: data/json/items/chemicals_and_resources.json @@ -44145,9 +44354,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "composition b" msgid_plural "composition b" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "composición B" +msgstr[1] "composición B" +msgstr[2] "composición B" #. ~ Description for {'str_sp': 'composition b'} #: data/json/items/chemicals_and_resources.json @@ -44182,9 +44391,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "improvised rocket fuel" msgid_plural "improvised rocket fuel" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "combustible de misiles improvisado" +msgstr[1] "combustible de misiles improvisado" +msgstr[2] "combustible de misiles improvisado" #. ~ Description for {'str_sp': 'improvised rocket fuel'} #: data/json/items/chemicals_and_resources.json @@ -44280,9 +44489,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "nanomaterial canister" msgid_plural "nanomaterial canisters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carcasa de nanomaterial" +msgstr[1] "carcasas de nanomaterial" +msgstr[2] "carcasas de nanomaterial" #. ~ Description for {'str': 'nanomaterial canister'} #: data/json/items/chemicals_and_resources.json @@ -44331,9 +44540,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "dimethyl sulfoxide" msgid_plural "dimethyl sulfoxide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dimetilsulfóxido" +msgstr[1] "dimetilsulfóxido" +msgstr[2] "dimetilsulfóxido" #. ~ Use action activation_message for {'str_sp': 'dimethyl sulfoxide'}. #: data/json/items/chemicals_and_resources.json @@ -44352,9 +44561,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "chloroform" msgid_plural "chloroform" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cloroformo" +msgstr[1] "cloroformo" +msgstr[2] "cloroformo" #. ~ Description for {'str_sp': 'chloroform'} #: data/json/items/chemicals_and_resources.json @@ -44370,9 +44579,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "phenol" msgid_plural "phenol" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fenol" +msgstr[1] "fenol" +msgstr[2] "fenol" #. ~ Description for {'str_sp': 'phenol'} #: data/json/items/chemicals_and_resources.json @@ -44391,9 +44600,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "peptone broth powder" msgid_plural "peptone broth powder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caldo de peptona" +msgstr[1] "caldo de peptona" +msgstr[2] "caldo de peptona" #. ~ Description for {'str_sp': 'peptone broth powder'} #: data/json/items/chemicals_and_resources.json @@ -44441,9 +44650,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "cobalt-60 pellet" msgid_plural "cobalt-60 pellets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolita cobalto-60" +msgstr[1] "bolitas cobalto-60" +msgstr[2] "bolitas cobalto-60" #. ~ Description for {'str': 'cobalt-60 pellet'} #: data/json/items/chemicals_and_resources.json @@ -44457,9 +44666,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "wooden bead" msgid_plural "wooden beads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cuenta de madera" +msgstr[1] "cuentas de madera" +msgstr[2] "cuentas de madera" #. ~ Description for {'str': 'wooden bead'} #: data/json/items/chemicals_and_resources.json @@ -44473,9 +44682,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "sandbag" msgid_plural "sandbags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de arena" +msgstr[1] "bolsas de arena" +msgstr[2] "bolsas de arena" #. ~ Description for {'str': 'sandbag'} #: data/json/items/chemicals_and_resources.json @@ -44489,9 +44698,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "earthbag" msgid_plural "earthbags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de tierra" +msgstr[1] "bolsas de tierra" +msgstr[2] "bolsas de tierra" #. ~ Description for {'str': 'earthbag'} #: data/json/items/chemicals_and_resources.json @@ -44519,9 +44728,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "rosin" msgid_plural "rosins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colofonia" +msgstr[1] "colofonia" +msgstr[2] "colofonia" #. ~ Description for {'str': 'rosin'} #: data/json/items/chemicals_and_resources.json @@ -44533,9 +44742,9 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "acetylene" msgid_plural "acetylene" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "acetileno" +msgstr[1] "acetileno" +msgstr[2] "acetileno" #. ~ Description for {'str_sp': 'acetylene'} #: data/json/items/chemicals_and_resources.json @@ -44643,9 +44852,9 @@ msgstr "Es una bolsa de plástico pequeña y abierta. Esencialmente, basura." #: data/json/items/containers.json msgid "zipper bag" msgid_plural "zipper bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa zipper" +msgstr[1] "bolsas zipper" +msgstr[2] "bolsas zipper" #. ~ Description for {'str': 'zipper bag'} #: data/json/items/containers.json @@ -44661,9 +44870,9 @@ msgstr "" #: data/json/items/containers.json msgid "body bag" msgid_plural "body bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de cadáver" +msgstr[1] "bolsas de cadáver" +msgstr[2] "bolsas de cadáver" #. ~ Description for {'str': 'body bag'} #: data/json/items/containers.json @@ -44677,9 +44886,9 @@ msgstr "" #: data/json/items/containers.json msgid "IV bag" msgid_plural "IV bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa IV" +msgstr[1] "bolsas IV" +msgstr[2] "bolsas IV" #. ~ Description for {'str': 'IV bag'} #: data/json/items/containers.json @@ -44717,9 +44926,9 @@ msgstr "" #: data/json/items/containers.json msgid "condiment bottle" msgid_plural "condiment bottles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "botella para condimento" +msgstr[1] "botellas para condimento" +msgstr[2] "botellas para condimento" #. ~ Description for {'str': 'condiment bottle'} #: data/json/items/containers.json @@ -44948,9 +45157,9 @@ msgstr "Es una bolsa de comida cerrada al vacío." #: data/json/items/containers.json msgid "small tin can" msgid_plural "small tin cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata pequeña de estaño" +msgstr[1] "latas pequeñas de estaño" +msgstr[2] "latas pequeñas de estaño" #. ~ Description for {'str': 'small tin can'} #: data/json/items/containers.json @@ -44960,9 +45169,9 @@ msgstr "Es una lata chica de estaño, como las del atún." #: data/json/items/containers.json msgid "small opened tin can" msgid_plural "small opened tin cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata pequeña de estaño abierta" +msgstr[1] "latas pequeñas de estaño abiertas" +msgstr[2] "latas pequeñas de estaño abiertas" #. ~ Description for {'str': 'small opened tin can'} #: data/json/items/containers.json @@ -44976,9 +45185,9 @@ msgstr "" #: data/json/items/containers.json msgid "medium tin can" msgid_plural "medium tin cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata mediana de estaño" +msgstr[1] "latas medianas de estaño" +msgstr[2] "latas medianas de estaño" #. ~ Description for {'str': 'medium tin can'} #: data/json/items/containers.json @@ -44988,9 +45197,9 @@ msgstr "Es una lata mediana de estaño, como las de tomate." #: data/json/items/containers.json msgid "medium opened tin can" msgid_plural "medium opened tin cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata mediana de estaño abierta" +msgstr[1] "latas medianas de estaño abiertas" +msgstr[2] "latas medianas de estaño abiertas" #. ~ Description for {'str': 'medium opened tin can'} #: data/json/items/containers.json @@ -45123,9 +45332,9 @@ msgstr "" #: data/json/items/containers.json msgid "test tube" msgid_plural "test tubes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tubo de ensayo" +msgstr[1] "tubos de ensayo" +msgstr[2] "tubos de ensayo" #. ~ Description for {'str': 'test tube'} #: data/json/items/containers.json @@ -45137,9 +45346,9 @@ msgstr "" #: data/json/items/containers.json msgid "beaker" msgid_plural "beakers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vaso de precipitado" +msgstr[1] "vasos de precipitado" +msgstr[2] "vasos de precipitado" #. ~ Description for {'str': 'beaker'} #: data/json/items/containers.json @@ -45152,9 +45361,9 @@ msgstr "" #: data/json/items/containers.json msgid "graduated cylinder" msgid_plural "graduated cylinders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "probetas" +msgstr[1] "probeta" +msgstr[2] "probeta" #. ~ Description for {'str': 'graduated cylinder'} #: data/json/items/containers.json @@ -45170,9 +45379,9 @@ msgstr "" #: data/json/items/containers.json msgid "microcentrifuge tube" msgid_plural "microcentrifuge tubes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tubo de microcentrífuga" +msgstr[1] "tubos de microcentrífuga" +msgstr[2] "tubos de microcentrífuga" #. ~ Description for {'str': 'microcentrifuge tube'} #: data/json/items/containers.json @@ -45526,9 +45735,9 @@ msgstr "Es un vasito descartable y barato con tapa plástica y pajita." #: data/json/items/containers.json msgid "plastic tub" msgid_plural "plastic tubs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "balde de plástico" +msgstr[1] "baldes de plástico" +msgstr[2] "baldes de plástico" #. ~ Description for {'str': 'plastic tub'} #: data/json/items/containers.json @@ -45540,9 +45749,9 @@ msgstr "" #: data/json/items/containers.json msgid "condom" msgid_plural "condoms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "preservativo" +msgstr[1] "preservativos" +msgstr[2] "preservativos" #. ~ Description for {'str': 'condom'} #: data/json/items/containers.json @@ -45558,9 +45767,9 @@ msgstr "" #: data/json/items/containers.json msgid "balloon" msgid_plural "balloons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "globo" +msgstr[1] "globos" +msgstr[2] "globos" #. ~ Description for {'str': 'balloon'} #: data/json/items/containers.json @@ -45572,9 +45781,9 @@ msgstr "" #: data/json/items/containers.json msgid "large tin can" msgid_plural "large tin cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata grande de estaño" +msgstr[1] "latas grandes de estaño" +msgstr[2] "latas grandes de estaño" #. ~ Description for {'str': 'large tin can'} #: data/json/items/containers.json @@ -45588,9 +45797,9 @@ msgstr "" #: data/json/items/containers.json msgid "large opened tin can" msgid_plural "large opened tin cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata grande de estaño abierta" +msgstr[1] "latas grandes de estaño abiertas" +msgstr[2] "latas grandes de estaño abiertas" #. ~ Description for {'str': 'large opened tin can'} #: data/json/items/containers.json @@ -45604,9 +45813,9 @@ msgstr "" #: data/json/items/containers.json msgid "survival kit box" msgid_plural "survival kit boxes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caja de kit de supervivencia" +msgstr[1] "cajas de kit de supervivencia" +msgstr[2] "cajas de kit de supervivencia" #. ~ Description for {'str': 'survival kit box', 'str_pl': 'survival kit #. boxes'} @@ -45709,16 +45918,16 @@ msgstr "" #: data/json/items/fake.json msgid "boulder anvil" msgid_plural "boulder anvils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "yunque de piedra" +msgstr[1] "yunques de piedra" +msgstr[2] "yunques de piedra" #: data/json/items/fake.json msgid "semi ground grains" msgid_plural "semi ground grains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "granos semimolidos" +msgstr[1] "granos semimolidos" +msgstr[2] "granos semimolidos" #. ~ Description for {'str_sp': 'semi ground grains'} #: data/json/items/fake.json @@ -45743,9 +45952,9 @@ msgstr "" #: data/json/items/fake.json msgid "bionic firestarter" msgid_plural "bionic firestarters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "magiclick biónico" +msgstr[1] "magiclicks biónicos" +msgstr[2] "magiclicks biónicos" #: data/json/items/fake.json msgid "mi-go bio-gun" @@ -45803,9 +46012,9 @@ msgstr "" #: data/json/items/fluff.json msgid "Magic 8-Ball" msgid_plural "Magic 8-Balls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Bola 8 Mágica" +msgstr[1] "Bolas 8 Mágicas" +msgstr[2] "Bolas 8 Mágicas" #. ~ Description for {'str': 'Magic 8-Ball'} #: data/json/items/fluff.json @@ -45819,9 +46028,9 @@ msgstr "" #: data/json/items/fluff.json data/mods/Fuji_Structures/items/items_games.json msgid "deck of cards" msgid_plural "decks of cards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mazo de cartas" +msgstr[1] "mazos de cartas" +msgstr[2] "mazos de cartas" #. ~ Description for {'str': 'deck of cards', 'str_pl': 'decks of cards'} #: data/json/items/fluff.json @@ -45831,9 +46040,9 @@ msgstr "Es un mazo de 52 cartas." #: data/json/items/fluff.json msgid "coin" msgid_plural "coins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "moneda" +msgstr[1] "monedas" +msgstr[2] "monedas" #. ~ Description for {'str': 'coin'} #: data/json/items/fluff.json @@ -45847,9 +46056,9 @@ msgstr "" #: data/json/items/fluff.json msgid "family photo" msgid_plural "family photos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "foto familiar" +msgstr[1] "fotos familiares" +msgstr[2] "fotos familiares" #. ~ Description for {'str': 'family photo'} #: data/json/items/fluff.json @@ -45881,9 +46090,9 @@ msgstr "" #: data/json/items/fuel.json msgid "denatured alcohol" msgid_plural "denatured alcohols" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "alcohol de quemar" +msgstr[1] "alcohol de quemar" +msgstr[2] "alcohol de quemar" #. ~ Description for {'str': 'denatured alcohol'} #: data/json/items/fuel.json @@ -45899,9 +46108,9 @@ msgstr "" #: data/json/items/fuel.json msgid "methanol" msgid_plural "methanols" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "metanol" +msgstr[1] "metanol" +msgstr[2] "metanol" #. ~ Description for {'str': 'methanol'} #: data/json/items/fuel.json @@ -45940,9 +46149,9 @@ msgstr "" #: data/json/items/fuel.json msgid "avgas fuel" msgid_plural "avgas fuel" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "combustible avgas" +msgstr[1] "combustible avgas" +msgstr[2] "combustible avgas" #. ~ Description for {'str_sp': 'avgas fuel'} #: data/json/items/fuel.json @@ -46009,9 +46218,9 @@ msgstr "" #: data/json/items/fuel.json msgid "gelled gasoline" msgid_plural "gelled gasoline" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nafta gel" +msgstr[1] "nafta gel" +msgstr[2] "nafta gel" #. ~ Description for {'str_sp': 'gelled gasoline'} #: data/json/items/fuel.json @@ -46027,9 +46236,9 @@ msgstr "" #: data/json/items/fuel.json msgid "flamethrower fuel" msgid_plural "flamethrower fuel" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "combustible para lanzallamas" +msgstr[1] "combustible para lanzallamas" +msgstr[2] "combustible para lanzallamas" #. ~ Description for {'str_sp': 'flamethrower fuel'} #: data/json/items/fuel.json @@ -46121,9 +46330,9 @@ msgstr[2] "" #: data/json/items/generic.json msgid "metabolism" msgid_plural "metabolisms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "metabolismo" +msgstr[1] "metabolismos" +msgstr[2] "metabolismos" #: data/json/items/generic.json msgid "nonsensoleum" @@ -46158,9 +46367,9 @@ msgstr "" #: data/json/items/generic.json msgid "INCIDENT REPORT: IMMERSION-27A" msgid_plural "INCIDENT REPORT: IMMERSION-27As" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "REPORTE DE INCIDENTE: INMERSIÓN-27A" +msgstr[1] "REPORTE DE INCIDENTE: INMERSIÓN-27A" +msgstr[2] "REPORTE DE INCIDENTE: INMERSIÓN-27A" #. ~ Description for {'str': 'INCIDENT REPORT: IMMERSION-27A'} #: data/json/items/generic.json @@ -46174,23 +46383,23 @@ msgstr "" #: data/json/items/generic.json msgid "MATERIAL: T-SUBSTRATE" msgid_plural "MATERIAL: T-SUBSTRATEs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MATERIAL: T-SUSTRATO" +msgstr[1] "MATERIAL: T-SUSTRATO" +msgstr[2] "MATERIAL: T-SUSTRATO" #: data/json/items/generic.json msgid "HAADF MICROGRAPH: T-SUBSTRATE" msgid_plural "HAADF MICROGRAPH: T-SUBSTRATEs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "HAADF MICROGRÁFICO: T-SUSTRATO" +msgstr[1] "HAADF MICROGRÁFICO: T-SUSTRATO" +msgstr[2] "HAADF MICROGRÁFICO: T-SUSTRATO" #: data/json/items/generic.json msgid "foodplace loyalty card" msgid_plural "foodplace loyalty cards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tarjeta de cliente de Foodplace" +msgstr[1] "tarjetas de cliente de Foodplace" +msgstr[2] "tarjetas de cliente de Foodplace" #. ~ Description for {'str': 'foodplace loyalty card'} #: data/json/items/generic.json @@ -46235,9 +46444,9 @@ msgstr "" #: data/json/items/generic.json msgid "faux fur pelt" msgid_plural "faux fur pelts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pelaje artificial" +msgstr[1] "pelajes artificiales" +msgstr[2] "pelajes artificiales" #. ~ Description for {'str': 'faux fur pelt'} #: data/json/items/generic.json @@ -46289,9 +46498,9 @@ msgstr "Un pequeño rollo de nomex, que es una tela ignífuga." #: data/json/items/generic.json msgid "superglue" msgid_plural "superglue" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "superpegamento" +msgstr[1] "superpegamento" +msgstr[2] "superpegamento" #. ~ Description for {'str_sp': 'superglue'} #: data/json/items/generic.json @@ -46359,9 +46568,9 @@ msgstr "Un pedazo del exoesqueleto de un insecto. Es liviano y muy duradero." #: data/json/items/generic.json msgid "set of 100 ceramic disk" msgid_plural "ceramic disks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "conjunto de 100 discos de cerámica" +msgstr[1] "discos de cerámica" +msgstr[2] "discos de cerámica" #. ~ Description for {'str': 'set of 100 ceramic disk', 'str_pl': 'ceramic #. disks'} @@ -46393,9 +46602,9 @@ msgstr "" #: data/json/items/generic.json msgid "bundle of rags" msgid_plural "bundles of rags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "paquete de trapos" +msgstr[1] "paquetes de trapos" +msgstr[2] "paquetes de trapos" #. ~ Description for {'str': 'bundle of rags', 'str_pl': 'bundles of rags'} #: data/json/items/generic.json @@ -46407,9 +46616,9 @@ msgstr "" #: data/json/items/generic.json msgid "bundle of leather" msgid_plural "bundles of leather" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "paquete de cueros" +msgstr[1] "paquetes de cueros" +msgstr[2] "paquetes de cueros" #. ~ Description for {'str': 'bundle of leather', 'str_pl': 'bundles of #. leather'} @@ -46424,9 +46633,9 @@ msgstr "" #: data/json/items/generic.json msgid "bundle of felt" msgid_plural "bundles of felt" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "paquete de fieltros" +msgstr[1] "paquetes de fieltros" +msgstr[2] "paquetes de fieltros" #. ~ Description for {'str': 'bundle of felt', 'str_pl': 'bundles of felt'} #: data/json/items/generic.json @@ -46439,9 +46648,9 @@ msgstr "" #: data/json/items/generic.json msgid "t-substrate sample" msgid_plural "t-substrate samples" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "muestra t-sustrato" +msgstr[1] "muestras t-sustrato" +msgstr[2] "muestras t-sustrato" #. ~ Description for {'str': 't-substrate sample'} #: data/json/items/generic.json @@ -46531,9 +46740,9 @@ msgstr "Es un pendrive con puerto USB. Útil para almacenar software." #: data/json/items/generic.json msgid "data card" msgid_plural "data cards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tarjeta de información" +msgstr[1] "tarjetas de información" +msgstr[2] "tarjetas de información" #. ~ Description for {'str': 'data card'} #: data/json/items/generic.json @@ -46590,9 +46799,9 @@ msgstr "" #: data/json/items/generic.json msgid "scythe blade" msgid_plural "scythe blades" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cuchilla de guadaña" +msgstr[1] "cuchillas de guadaña" +msgstr[2] "cuchillas de guadaña" #. ~ Description for {'str': 'scythe blade'} #: data/json/items/generic.json @@ -46669,9 +46878,9 @@ msgstr "Un pedazo de alambre rígido, cubierto con púas puntiagudas." #: data/json/items/generic.json msgid "steel mesh" msgid_plural "steel meshes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "malla de acero" +msgstr[1] "mallas de acero" +msgstr[2] "mallas de acero" #. ~ Description for {'str': 'steel mesh', 'str_pl': 'steel meshes'} #: data/json/items/generic.json @@ -46834,9 +47043,9 @@ msgstr "" #: data/json/items/generic.json msgid "bimetal thermostat" msgid_plural "bimetal thermostats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "termostato bimetálico" +msgstr[1] "termostatos bimetálicos" +msgstr[2] "termostatos bimetálicos" #. ~ Description for {'str': 'bimetal thermostat'} #: data/json/items/generic.json @@ -46877,9 +47086,9 @@ msgstr "" #: data/json/items/generic.json msgid "delayed fuze" msgid_plural "delayed fuzes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mecha retrasada" +msgstr[1] "mechas retrasadas" +msgstr[2] "mechas retrasadas" #. ~ Description for delayed fuze #: data/json/items/generic.json @@ -46893,9 +47102,9 @@ msgstr "" #: data/json/items/generic.json msgid "impact fuze" msgid_plural "impact fuzes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mecha de impacto" +msgstr[1] "mechas de impacto" +msgstr[2] "mechas de impacto" #. ~ Description for impact fuze #: data/json/items/generic.json @@ -46984,9 +47193,9 @@ msgstr "" #: data/json/items/generic.json msgid "broken lab defense bot" msgid_plural "broken lab defense bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "robot defensor de laboratorio roto" +msgstr[1] "robots defensores de laboratorio rotos" +msgstr[2] "robots defensores de laboratorio rotos" #. ~ Description for {'str': 'broken lab defense bot'} #: data/json/items/generic.json @@ -47016,9 +47225,9 @@ msgstr "" #: data/json/items/generic.json msgid "broken nurse bot" msgid_plural "broken nurse bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "enfermerobot roto" +msgstr[1] "enfermerobots rotos" +msgstr[2] "enfermerobots rotos" #. ~ Description for {'str': 'broken nurse bot'} #: data/json/items/generic.json @@ -47032,9 +47241,9 @@ msgstr "" #: data/json/items/generic.json msgid "broken grocery bot" msgid_plural "broken grocery bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "reposibot roto" +msgstr[1] "reposibots rotos" +msgstr[2] "reposibots rotos" #. ~ Description for {'str': 'broken grocery bot'} #: data/json/items/generic.json @@ -47087,9 +47296,9 @@ msgstr "" #: data/json/items/generic.json msgid "broken prototype robot" msgid_plural "broken prototype robots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "robot prototipo roto" +msgstr[1] "robots prototipo rotos" +msgstr[2] "robots prototipo rotos" #. ~ Description for {'str': 'broken prototype robot'} #: data/json/items/generic.json @@ -47120,9 +47329,9 @@ msgstr "" #: data/json/items/generic.json msgid "broken recon mech" msgid_plural "broken recon mechs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mecha de reconocimiento roto" +msgstr[1] "mechas de reconocimiento rotos" +msgstr[2] "mechas de reconocimiento rotos" #. ~ Description for {'str': 'broken recon mech'} #. ~ Description for {'str': 'broken mech lifter'} @@ -47135,23 +47344,23 @@ msgstr "" #: data/json/items/generic.json msgid "broken mech lifter" msgid_plural "broken mech lifters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mecha de levantamiento roto" +msgstr[1] "mechas de levantamiento rotos" +msgstr[2] "mechas de levantamiento rotos" #: data/json/items/generic.json msgid "broken combat mech" msgid_plural "broken combat mechs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mecha de combate roto" +msgstr[1] "mechas de combate rotos" +msgstr[2] "mechas de combate rotos" #: data/json/items/generic.json msgid "broken riot dispatch" msgid_plural "broken riot dispatches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "desplegador de disturbios roto" +msgstr[1] "desplegadores de disturbios rotos" +msgstr[2] "desplegadores de disturbios rotos" #. ~ Description for {'str': 'broken riot dispatch', 'str_pl': 'broken riot #. dispatches'} @@ -47167,9 +47376,9 @@ msgstr "" #: data/json/items/generic.json msgid "broken military dispatch" msgid_plural "broken military dispatches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "desplegador militar roto" +msgstr[1] "desplegadores militares rotos" +msgstr[2] "desplegadores militares rotos" #. ~ Description for {'str': 'broken military dispatch', 'str_pl': 'broken #. military dispatches'} @@ -47394,9 +47603,9 @@ msgstr "" #: data/json/items/generic.json msgid "large LCD screen" msgid_plural "large LCD screens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pantalla LCD grande" +msgstr[1] "pantallas LCD grandes" +msgstr[2] "pantallas LCD grandes" #. ~ Description for {'str': 'large LCD screen'} #: data/json/items/generic.json @@ -47443,9 +47652,9 @@ msgstr "" #: data/json/items/generic.json msgid "small high-quality lens" msgid_plural "small high-quality lenses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lente pequeño de alta calidad" +msgstr[1] "lentes pequeños de alta calidad" +msgstr[2] "lentes pequeños de alta calidad" #. ~ Description for {'str': 'small high-quality lens', 'str_pl': 'small high- #. quality lenses'} @@ -47460,9 +47669,9 @@ msgstr "" #: data/json/items/generic.json msgid "pair of tinted glass" msgid_plural "pairs of tinted glass" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de anteojos polarizados" +msgstr[1] "pares de anteojos polarizados" +msgstr[2] "pares de anteojos polarizados" #. ~ Description for {'str': 'pair of tinted glass', 'str_pl': 'pairs of #. tinted glass'} @@ -47512,9 +47721,9 @@ msgstr "" #: data/json/items/generic.json msgid "nanofabricator template (silicon photonics)" msgid_plural "nanofabricator templates (silicon photonics)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "plantilla para nanofabricador (fotónica con silicona)" +msgstr[1] "plantillas para nanofabricador (fotónica con silicona)" +msgstr[2] "plantillas para nanofabricador (fotónica con silicona)" #. ~ Description for {'str': 'nanofabricator template (silicon photonics)', #. 'str_pl': 'nanofabricator templates (silicon photonics)'} @@ -47548,9 +47757,9 @@ msgstr "" #: data/json/items/generic.json msgid "micro motor" msgid_plural "micro motors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "micro motor" +msgstr[1] "micro motores" +msgstr[2] "micro motores" #. ~ Description for {'str': 'micro motor'} #: data/json/items/generic.json @@ -47639,9 +47848,9 @@ msgstr "" #: data/json/items/generic.json msgid "fishbowl" msgid_plural "fishbowls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pecera" +msgstr[1] "peceras" +msgstr[2] "peceras" #. ~ Description for {'str': 'fishbowl'} #: data/json/items/generic.json @@ -47669,9 +47878,9 @@ msgstr "" #: data/json/items/generic.json msgid "pipe cleaner" msgid_plural "pipe cleaners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "destapacañerías" +msgstr[1] "destapacañerías" +msgstr[2] "destapacañerías" #. ~ Description for {'str': 'pipe cleaner'} #: data/json/items/generic.json @@ -47851,9 +48060,9 @@ msgstr "" #: data/json/items/generic.json msgid "chamomile flowers" msgid_plural "chamomile flowers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flores de manzanilla" +msgstr[1] "flores de manzanilla" +msgstr[2] "flores de manzanilla" #. ~ Description for {'str_sp': 'chamomile flowers'} #: data/json/items/generic.json @@ -47866,16 +48075,16 @@ msgstr "" #: data/json/items/generic.json msgid "lotus flower" msgid_plural "lotus flowers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flor de loto" +msgstr[1] "flores de loto" +msgstr[2] "flores de loto" #: data/json/items/generic.json msgid "spurge flowers" msgid_plural "spurge flowers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flor de euforbio" +msgstr[1] "flores de euforbio" +msgstr[2] "flores de euforbio" #. ~ Description for {'str_sp': 'spurge flowers'} #: data/json/items/generic.json @@ -47926,9 +48135,9 @@ msgstr "Es un poco de mortero, listo para ser usado en alguna construcción." #: data/json/items/generic.json msgid "soft adobe brick" msgid_plural "soft adobe bricks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ladrillo blando de adobe" +msgstr[1] "ladrillos blandos de adobe" +msgstr[2] "ladrillos blandos de adobe" #. ~ Use action msg for {'str': 'soft adobe brick'}. #: data/json/items/generic.json @@ -47950,9 +48159,9 @@ msgstr "" #: data/json/items/generic.json msgid "adobe brick" msgid_plural "adobe bricks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ladrillo de adobe" +msgstr[1] "ladrillos de adobe" +msgstr[2] "ladrillos de adobe" #. ~ Description for {'str': 'adobe brick'} #: data/json/items/generic.json @@ -47966,9 +48175,9 @@ msgstr "" #: data/json/items/generic.json msgid "adobe mortar" msgid_plural "adobe mortar" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mezcla de adobe" +msgstr[1] "mezcla de adobe" +msgstr[2] "mezcla de adobe" #. ~ Description for {'str_sp': 'adobe mortar'} #: data/json/items/generic.json @@ -47983,9 +48192,9 @@ msgstr "" #: data/json/items/generic.json msgid "tanbark" msgid_plural "tanbark" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casca" +msgstr[1] "casca" +msgstr[2] "casca" #. ~ Description for {'str_sp': 'tanbark'} #: data/json/items/generic.json @@ -48009,9 +48218,9 @@ msgstr "" #: data/json/items/generic.json msgid "willowbark" msgid_plural "willowbark" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cortezas de sauce" +msgstr[1] "corteza de sauce" +msgstr[2] "corteza de sauce" #. ~ Description for {'str_sp': 'willowbark'} #: data/json/items/generic.json @@ -48037,9 +48246,9 @@ msgstr "Un diamante brillante." #: data/json/items/generic.json msgid "garnet" msgid_plural "garnets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "granate" +msgstr[1] "granates" +msgstr[2] "granates" #. ~ Description for {'str': 'garnet'} #: data/json/items/generic.json @@ -48049,9 +48258,9 @@ msgstr "Es un granate brillante." #: data/json/items/generic.json msgid "amethyst" msgid_plural "amethysts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "amatista" +msgstr[1] "amatistas" +msgstr[2] "amatistas" #. ~ Description for {'str': 'amethyst'} #: data/json/items/generic.json @@ -48061,9 +48270,9 @@ msgstr "Es una amatista brillante." #: data/json/items/generic.json msgid "aquamarine" msgid_plural "aquamarines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aguamarina" +msgstr[1] "aguamarinas" +msgstr[2] "aguamarinas" #. ~ Description for {'str': 'aquamarine'} #: data/json/items/generic.json @@ -48073,9 +48282,9 @@ msgstr "Es una aguamarina brillante." #: data/json/items/generic.json msgid "emerald" msgid_plural "emeralds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esmeralda" +msgstr[1] "esmeraldas" +msgstr[2] "esmeraldas" #. ~ Description for {'str': 'emerald'} #: data/json/items/generic.json @@ -48085,9 +48294,9 @@ msgstr "Es una esmeralda brillante." #: data/json/items/generic.json msgid "alexandrite" msgid_plural "alexandrites" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "alejandrita" +msgstr[1] "alejandritas" +msgstr[2] "alejandritas" #. ~ Description for {'str': 'alexandrite'} #: data/json/items/generic.json @@ -48097,9 +48306,9 @@ msgstr "Es una alejandrita brillante." #: data/json/items/generic.json msgid "pearl" msgid_plural "pearls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perla" +msgstr[1] "perlas" +msgstr[2] "perlas" #. ~ Description for {'str': 'pearl'} #: data/json/items/generic.json @@ -48109,9 +48318,9 @@ msgstr "Es una perla lustrosa." #: data/json/items/generic.json msgid "ruby" msgid_plural "rubies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rubí" +msgstr[1] "rubíes" +msgstr[2] "rubíes" #. ~ Description for {'str': 'ruby', 'str_pl': 'rubies'} #: data/json/items/generic.json @@ -48121,9 +48330,9 @@ msgstr "Es un rubí brillante." #: data/json/items/generic.json msgid "peridot" msgid_plural "peridots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "peridoto" +msgstr[1] "peridotos" +msgstr[2] "peridotos" #. ~ Description for {'str': 'peridot'} #: data/json/items/generic.json @@ -48133,9 +48342,9 @@ msgstr "Es un peridoto brillante." #: data/json/items/generic.json msgid "sapphire" msgid_plural "sapphires" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zafiro" +msgstr[1] "zafiros" +msgstr[2] "zafiros" #. ~ Description for {'str': 'sapphire'} #: data/json/items/generic.json @@ -48145,9 +48354,9 @@ msgstr "Es un zafiro brillante." #: data/json/items/generic.json msgid "opal" msgid_plural "opals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ópalo" +msgstr[1] "ópalos" +msgstr[2] "ópalos" #. ~ Description for {'str': 'opal'} #: data/json/items/generic.json @@ -48157,9 +48366,9 @@ msgstr "Es un ópalo lustroso." #: data/json/items/generic.json msgid "tourmaline" msgid_plural "tourmalines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "turmalina" +msgstr[1] "turmalinas" +msgstr[2] "turmalinas" #. ~ Description for {'str': 'tourmaline'} #: data/json/items/generic.json @@ -48169,9 +48378,9 @@ msgstr "Es una turmalina brillante." #: data/json/items/generic.json msgid "citrine" msgid_plural "citrines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "citrino" +msgstr[1] "citrinos" +msgstr[2] "citrinos" #. ~ Description for {'str': 'citrine'} #: data/json/items/generic.json @@ -48181,9 +48390,9 @@ msgstr "Es un citrino brillante." #: data/json/items/generic.json msgid "topaz" msgid_plural "topazs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "topacio" +msgstr[1] "topacios" +msgstr[2] "topacios" #. ~ Description for {'str': 'topaz'} #: data/json/items/generic.json @@ -48331,9 +48540,9 @@ msgstr "" #: data/json/items/generic.json msgid "autoclave pouch" msgid_plural "autoclave pouches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa autoclave" +msgstr[1] "bolsas autoclave" +msgstr[2] "bolsas autoclave" #. ~ Description for {'str': 'autoclave pouch', 'str_pl': 'autoclave pouches'} #: data/json/items/generic.json @@ -48495,9 +48704,9 @@ msgstr "" #: data/json/items/generic.json msgid "raw tobacco" msgid_plural "raw tobacco" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tabaco crudo" +msgstr[1] "tabaco crudo" +msgstr[2] "tabaco crudo" #. ~ Description for {'str_sp': 'raw tobacco'} #: data/json/items/generic.json @@ -48616,9 +48825,9 @@ msgstr "" #: data/json/items/generic.json msgid "industrial ID card" msgid_plural "industrial ID cards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carné de industrial" +msgstr[1] "carnés de industrial" +msgstr[2] "carnés de industrial" #. ~ Description for {'str': 'industrial ID card'} #: data/json/items/generic.json @@ -48634,9 +48843,9 @@ msgstr "" #: data/json/items/generic.json msgid "neoprene patch" msgid_plural "neoprene patches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fragmento de neopreno" +msgstr[1] "fragmentos de neopreno" +msgstr[2] "fragmentos de neopreno" #. ~ Description for {'str': 'neoprene patch', 'str_pl': 'neoprene patches'} #: data/json/items/generic.json @@ -48709,9 +48918,9 @@ msgstr "" #: data/json/items/generic.json msgid "shrapnel" msgid_plural "shrapnels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquirla" +msgstr[1] "esquirlas" +msgstr[2] "esquirlas" #. ~ Description for {'str': 'shrapnel'} #: data/json/items/generic.json @@ -48721,9 +48930,9 @@ msgstr "Es un pedazo de metal retorcido y con puntas." #: data/json/items/generic.json msgid "clay flower pot" msgid_plural "clay flower pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maceta de arcilla" +msgstr[1] "macetas de arcilla" +msgstr[2] "macetas de arcilla" #. ~ Description for {'str': 'clay flower pot'} #: data/json/items/generic.json @@ -48733,9 +48942,9 @@ msgstr "Es una linda maceta de arcilla en la que se puede plantar algo." #: data/json/items/generic.json msgid "plastic flower pot" msgid_plural "plastic flower pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maceta de plástico" +msgstr[1] "macetas de plástico" +msgstr[2] "macetas de plástico" #. ~ Description for {'str': 'plastic flower pot'} #: data/json/items/generic.json @@ -48760,9 +48969,9 @@ msgstr "" #: data/json/items/generic.json msgid "evaporator coil" msgid_plural "evaporator coils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bobina evaporadora" +msgstr[1] "bobinas evaporadoras" +msgstr[2] "bobinas evaporadoras" #. ~ Description for {'str': 'evaporator coil'} #: data/json/items/generic.json @@ -48774,9 +48983,9 @@ msgstr "" #: data/json/items/generic.json msgid "condensor coil" msgid_plural "condensor coils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bobina condensadora" +msgstr[1] "bobinas condensadoras" +msgstr[2] "bobinas condensadoras" #. ~ Description for {'str': 'condensor coil'} #: data/json/items/generic.json @@ -48839,9 +49048,9 @@ msgstr "" #: data/json/items/generic.json msgid "small lock and key" msgid_plural "small locks and keys" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "llave y candado pequeño" +msgstr[1] "llaves y candados pequeños" +msgstr[2] "llaves y candados pequeños" #. ~ Description for {'str': 'small lock and key', 'str_pl': 'small locks and #. keys'} @@ -48852,9 +49061,9 @@ msgstr "Es un candado chico, con unas llaves puestas." #: data/json/items/generic.json msgid "in progress craft" msgid_plural "in progress crafts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fabricación en progreso" +msgstr[1] "fabricaciones en progreso" +msgstr[2] "fabricaciones en progreso" #. ~ Description for {'str': 'in progress craft'} #: data/json/items/generic.json @@ -48864,9 +49073,9 @@ msgstr "Esto es una fabricación en progreso." #: data/json/items/generic.json msgid "spare tire carrier" msgid_plural "spare tire carriers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "porta rueda de auxilio" +msgstr[1] "porta rueda de auxilio" +msgstr[2] "porta rueda de auxilio" #. ~ Description for {'str': 'spare tire carrier'} #: data/json/items/generic.json @@ -48880,9 +49089,9 @@ msgstr "" #: data/json/items/generic.json msgid "welding component kit" msgid_plural "welding component kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "equipo de soldadura" +msgstr[1] "equipos de soldadura" +msgstr[2] "equipos de soldadura" #. ~ Description for {'str': 'welding component kit'} #: data/json/items/generic.json @@ -48896,9 +49105,9 @@ msgstr "" #: data/json/items/generic.json msgid "amplifier head" msgid_plural "amplifier heads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cabezal de amplificador" +msgstr[1] "cabezales de amplificador" +msgstr[2] "cabezales de amplificador" #. ~ Description for {'str': 'amplifier head'} #: data/json/items/generic.json @@ -48953,9 +49162,9 @@ msgstr[2] "torretas láseres rotas" #: data/json/items/generic.json msgid "broken secubot" msgid_plural "broken secubots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "secubot roto" +msgstr[1] "secubots rotos" +msgstr[2] "secubots rotos" #. ~ Description for {'str': 'broken secubot'} #: data/json/items/generic.json @@ -48969,9 +49178,9 @@ msgstr "" #: data/json/items/generic.json msgid "broken M202A1 TALON" msgid_plural "broken M202A1 TALONs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "M202A1 TALON roto" +msgstr[1] "M202A1 TALON rotos" +msgstr[2] "M202A1 TALON rotos" #. ~ Description for {'str': 'broken M202A1 TALON'} #. ~ Description for {'str': 'broken launcher TALON UGV'} @@ -48987,9 +49196,9 @@ msgstr "" #: data/json/items/generic.json msgid "fire brick" msgid_plural "fire bricks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ladrillo refractario" +msgstr[1] "ladrillos refractarios" +msgstr[2] "ladrillos refractarios" #. ~ Description for {'str': 'fire brick'} #: data/json/items/generic.json @@ -49001,9 +49210,9 @@ msgstr "" #: data/json/items/generic.json msgid "survival kit" msgid_plural "survival kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "kit de supervivencia" +msgstr[1] "kits de supervivencia" +msgstr[2] "kits de supervivencia" #. ~ Description for {'str': 'survival kit'} #: data/json/items/generic.json @@ -49030,9 +49239,9 @@ msgstr "" #: data/json/items/generic.json msgid "plastic dice" msgid_plural "plastic dice" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dado de plástico" +msgstr[1] "dados de plástico" +msgstr[2] "dados de plástico" #. ~ Description for {'str_sp': 'plastic dice'} #: data/json/items/generic.json @@ -49042,9 +49251,9 @@ msgstr "Es un dado de plástico de seis cara." #: data/json/items/generic.json msgid "salt lick" msgid_plural "salt licks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bloque de sal" +msgstr[1] "bloques de sal" +msgstr[2] "bloques de sal" #. ~ Description for {'str': 'salt lick'} #: data/json/items/generic.json @@ -49228,9 +49437,9 @@ msgstr "" #: data/json/items/newspaper.json msgid "character sheet" msgid_plural "character sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "planilla de personaje" +msgstr[1] "planillas de personaje" +msgstr[2] "planillas de personaje" #. ~ Description for {'str': 'character sheet'} #: data/json/items/newspaper.json @@ -49363,9 +49572,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "module template" msgid_plural "module templates" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "plantilla de módulo" +msgstr[1] "plantillas de módulo" +msgstr[2] "plantillas de módulo" #. ~ Description for {'str': 'module template'} #: data/json/items/robot_parts.json @@ -49377,9 +49586,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "targeting module" msgid_plural "targeting modules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "módulo de objetivo" +msgstr[1] "módulos de objetivo" +msgstr[2] "módulos de objetivo" #. ~ Description for {'str': 'targeting module'} #: data/json/items/robot_parts.json @@ -49394,9 +49603,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "identification module" msgid_plural "identification modules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "módulo de identificación" +msgstr[1] "módulos de identificación" +msgstr[2] "módulos de identificación" #. ~ Description for {'str': 'identification module'} #: data/json/items/robot_parts.json @@ -49410,9 +49619,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "pathfinding module" msgid_plural "pathfinding modules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "módulo de reconocimiento" +msgstr[1] "módulos de reconocimiento" +msgstr[2] "módulos de reconocimiento" #. ~ Description for {'str': 'pathfinding module'} #: data/json/items/robot_parts.json @@ -49426,9 +49635,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "memory banks module" msgid_plural "memory banks modules" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "módulo de memoria" +msgstr[1] "módulos de memoria" +msgstr[2] "módulos de memoria" #. ~ Description for {'str': 'memory banks module'} #: data/json/items/robot_parts.json @@ -49438,9 +49647,9 @@ msgstr "Este módulo permite almacenar y recuperar información." #: data/json/items/robot_parts.json msgid "sensor array" msgid_plural "sensor arrays" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "matriz de sensores" +msgstr[1] "matrices de sensores" +msgstr[2] "matrices de sensores" #. ~ Description for {'str': 'sensor array'} #: data/json/items/robot_parts.json @@ -49454,9 +49663,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "self monitoring sensors" msgid_plural "self monitoring sensors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sensores de automonitoreo" +msgstr[1] "sensores de automonitoreo" +msgstr[2] "sensores de automonitoreo" #. ~ Description for {'str_sp': 'self monitoring sensors'} #: data/json/items/robot_parts.json @@ -49486,9 +49695,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "basic AI core" msgid_plural "basic AI cores" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "núcleo básico de IA" +msgstr[1] "núcleos básicos de IA" +msgstr[2] "núcleos básicos de IA" #. ~ Description for {'str': 'basic AI core'} #: data/json/items/robot_parts.json @@ -49498,9 +49707,9 @@ msgstr "Es un núcleo muy básico de IA con las mínimas habilidades cognitivas. #: data/json/items/robot_parts.json msgid "advanced AI core" msgid_plural "advanced AI cores" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "núcleo avanzado de IA" +msgstr[1] "núcleos avanzados de IA" +msgstr[2] "núcleos avanzados de IA" #. ~ Description for {'str': 'advanced AI core'} #: data/json/items/robot_parts.json @@ -49511,9 +49720,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "gun operating system" msgid_plural "gun operating systems" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sistema de operación de armas" +msgstr[1] "sistemas de operación de armas" +msgstr[2] "sistemas de operación de armas" #. ~ Description for {'str': 'gun operating system'} #: data/json/items/robot_parts.json @@ -49523,9 +49732,9 @@ msgstr "Este sistema puede operar la mayoría de armas convencionales." #: data/json/items/robot_parts.json msgid "set of tiny spidery legs" msgid_plural "sets of tiny spidery legs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grupo de pequeñas piernas arácnidas" +msgstr[1] "grupos de pequeñas piernas arácnidas" +msgstr[2] "grupos de pequeñas piernas arácnidas" #. ~ Description for {'str': 'set of tiny spidery legs', 'str_pl': 'sets of #. tiny spidery legs'} @@ -49537,9 +49746,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "set of reverse-jointed legs" msgid_plural "sets of reverse-jointed legs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grupo de piernas con articulaciones inversas" +msgstr[1] "grupos de piernas con articulaciones inversas" +msgstr[2] "grupos de piernas con articulaciones inversas" #. ~ Description for {'str': 'set of reverse-jointed legs', 'str_pl': 'sets of #. reverse-jointed legs'} @@ -49553,9 +49762,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "set of omni wheels" msgid_plural "sets of omni wheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grupo de ruedas multidireccionales" +msgstr[1] "grupos de ruedas multidireccionales" +msgstr[2] "grupos de ruedas multidireccionales" #. ~ Description for {'str': 'set of omni wheels', 'str_pl': 'sets of omni #. wheels'} @@ -49567,9 +49776,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "set of rotors" msgid_plural "sets of rotors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grupo de rotores" +msgstr[1] "grupos de rotores" +msgstr[2] "grupos de rotores" #. ~ Description for {'str': 'set of rotors', 'str_pl': 'sets of rotors'} #: data/json/items/robot_parts.json @@ -49579,9 +49788,9 @@ msgstr "Es un grupo de rotores que pueden levantar a un pequeño drone." #: data/json/items/robot_parts.json msgid "set of android legs" msgid_plural "sets of android legs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grupo de piernas androides" +msgstr[1] "grupos de piernas androides" +msgstr[2] "grupos de piernas androides" #. ~ Description for {'str': 'set of android legs', 'str_pl': 'sets of android #. legs'} @@ -49592,9 +49801,9 @@ msgstr "Es un grupo de piernas similares a las humanas." #: data/json/items/robot_parts.json msgid "set of android arms" msgid_plural "sets of android arms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grupo de brazos androides" +msgstr[1] "grupos de brazos androides" +msgstr[2] "grupos de brazos androides" #. ~ Description for {'str': 'set of android arms', 'str_pl': 'sets of android #. arms'} @@ -49605,9 +49814,9 @@ msgstr "Es un grupo de brazos similares a las humanos." #: data/json/items/robot_parts.json msgid "set of small tank tread" msgid_plural "sets of small tank tread" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de orugas pequeñas de tanque" +msgstr[1] "pares de orugas pequeñas de tanque" +msgstr[2] "pares de orugas pequeñas de tanque" #. ~ Description for {'str': 'set of small tank tread', 'str_pl': 'sets of #. small tank tread'} @@ -49620,9 +49829,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "turret interior chassis" msgid_plural "turret interior chassis" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chasis interior de torreta" +msgstr[1] "chasis interiores de torreta" +msgstr[2] "chasis interiores de torreta" #. ~ Description for {'str_sp': 'turret interior chassis'} #: data/json/items/robot_parts.json @@ -49650,9 +49859,9 @@ msgstr "" #: data/json/items/robot_parts.json msgid "android skeleton" msgid_plural "android skeletons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esqueleto androide" +msgstr[1] "esqueletos androides" +msgstr[2] "esqueletos androides" #. ~ Description for {'str': 'android skeleton'} #: data/json/items/robot_parts.json @@ -50046,9 +50255,9 @@ msgstr "" #: data/json/items/software.json src/cata_tiles.cpp src/options.cpp msgid "software" msgid_plural "software" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "software" +msgstr[1] "software" +msgstr[2] "software" #: data/json/items/software.json msgid "misc software" @@ -50138,9 +50347,9 @@ msgstr "" #: data/json/items/software.json msgid "neural data" msgid_plural "neural data" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "información neural" +msgstr[1] "información neural" +msgstr[2] "información neural" #. ~ Description for {'str_sp': 'neural data'} #: data/json/items/software.json @@ -50156,9 +50365,9 @@ msgstr "" #: data/json/items/software.json msgid "integrated circuit datasheet archives" msgid_plural "misc software" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "software variado" +msgstr[1] "software variado" +msgstr[2] "software variado" #. ~ Description for {'str': 'integrated circuit datasheet archives', #. 'str_pl': 'misc software'} @@ -50190,9 +50399,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "arm splint XL" msgid_plural "arm splints XL" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tablilla para brazo XL" +msgstr[1] "tablillas para brazo XL" +msgstr[2] "tablillas para brazo XL" #. ~ Description for {'str': 'arm splint XL', 'str_pl': 'arm splints XL'} #: data/json/items/tool_armor.json @@ -50254,9 +50463,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "personal go bag" msgid_plural "personal go bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolso de evacuación personal" +msgstr[1] "bolsos de evacuación personales" +msgstr[2] "bolsos de evacuación personales" #. ~ Description for {'str': 'personal go bag'} #: data/json/items/tool_armor.json @@ -50278,9 +50487,9 @@ msgstr[2] "tablillas para piernas" #: data/json/items/tool_armor.json msgid "leg splint XL" msgid_plural "leg splints XL" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tablilla para pierna XL" +msgstr[1] "tablillas para pierna XL" +msgstr[2] "tablillas para pierna XL" #. ~ Description for {'str': 'leg splint XL', 'str_pl': 'leg splints XL'} #: data/json/items/tool_armor.json @@ -50380,9 +50589,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "crude welding mask" msgid_plural "crude welding masks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "careta rudimentaria de soldador" +msgstr[1] "caretas rudimentarias de soldador" +msgstr[2] "caretas rudimentarias de soldador" #. ~ Description for {'str': 'crude welding mask'} #: data/json/items/tool_armor.json @@ -50399,9 +50608,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "crude welding mask (raised)" msgid_plural "crude welding masks (raised)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "careta rudimentaria de soldador (levantada)" +msgstr[1] "caretas rudimentarias de soldador (levantadas)" +msgstr[2] "caretas rudimentarias de soldador (levantadas)" #. ~ Use action menu_text for {'str': 'crude welding mask (raised)', 'str_pl': #. 'crude welding masks (raised)'}. @@ -50433,9 +50642,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "welding mask (raised)" msgid_plural "welding masks (raised)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "careta de soldador (levantada)" +msgstr[1] "caretas de soldador (levantadas)" +msgstr[2] "caretas de soldador (levantadas)" #. ~ Use action msg for {'str': 'welding mask (raised)', 'str_pl': 'welding #. masks (raised)'}. @@ -50472,9 +50681,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "hologram cloak" msgid_plural "hologram cloaks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capa de holograma" +msgstr[1] "capas de holograma" +msgstr[2] "capas de holograma" #. ~ Description for {'str': 'hologram cloak'} #: data/json/items/tool_armor.json @@ -50792,9 +51001,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "survivor headlamp" msgid_plural "survivor headlamps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "faro delantero de supervivencia" +msgstr[1] "faros delanteros de supervivencia" +msgstr[2] "faros delanteros de supervivencia" #. ~ Use action msg for {'str': 'survivor headlamp'}. #: data/json/items/tool_armor.json @@ -50818,9 +51027,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "survivor headlamp (on)" msgid_plural "survivor headlamps (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "faro delantero de supervivencia (enc.)" +msgstr[1] "faros delanteros de supervivencia (enc.)" +msgstr[2] "faros delanteros de supervivencia (enc.)" #. ~ Description for {'str': 'survivor headlamp (on)', 'str_pl': 'survivor #. headlamps (on)'} @@ -52390,9 +52599,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "solar backpack (folded)" msgid_plural "solar backpacks (folded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochila solar (plegada)" +msgstr[1] "mochilas solares (plegadas)" +msgstr[2] "mochilas solares (plegadas)" #. ~ Description for {'str': 'solar backpack (folded)', 'str_pl': 'solar #. backpacks (folded)'} @@ -52595,9 +52804,9 @@ msgstr[2] "" #: data/json/items/tool_armor.json msgid "pair of attached ear plugs (in)" msgid_plural "pairs of attached ear plugs (in)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de tapones para los oídos unidos (puesto)" +msgstr[1] "pares de tapones para los oídos unidos (puestos)" +msgstr[2] "pares de tapones para los oídos unidos (puestos)" #. ~ Use action menu_text for {'str': 'pair of attached ear plugs (in)', #. 'str_pl': 'pairs of attached ear plugs (in)'}. @@ -52624,9 +52833,9 @@ msgstr "" #: data/json/items/tool_armor.json msgid "pair of attached ear plugs (out)" msgid_plural "pairs of attached ear plugs (out)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de tapones para los oídos unidos" +msgstr[1] "pares de tapones para los oídos unidos" +msgstr[2] "pares de tapones para los oídos unidos" #. ~ Use action menu_text for {'str': 'pair of attached ear plugs (out)', #. 'str_pl': 'pairs of attached ear plugs (out)'}. @@ -52735,9 +52944,9 @@ msgstr "" #: data/json/items/ammo/10mm.json msgid "10mm Auto FMJ" msgid_plural "10mm Auto FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "10mm Auto FMJ" +msgstr[1] "10mm Auto FMJ" +msgstr[2] "10mm Auto FMJ" #. ~ Description for {'str': '10mm Auto FMJ'} #: data/json/items/ammo/10mm.json @@ -52751,16 +52960,16 @@ msgstr "" #: data/json/items/ammo/10mm.json msgid "10mm Auto FMJ, black powder" msgid_plural "10mm Auto FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "10mm Auto FMJ, pólvora" +msgstr[1] "10mm Auto FMJ, pólvora" +msgstr[2] "10mm Auto FMJ, pólvora" #: data/json/items/ammo/12mm.json msgid "H&K 12mm" msgid_plural "H&K 12mms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "H&K 12mm" +msgstr[1] "H&K 12mm" +msgstr[2] "H&K 12mm" #. ~ Description for {'str': 'H&K 12mm'} #: data/json/items/ammo/12mm.json @@ -52792,54 +53001,46 @@ msgstr "" #: data/json/items/ammo/20x66mm.json msgid "20x66mm flechette, handmade" msgid_plural "20x66mm flechettes, handmade" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "20x66mm dardos perforantes, casera" +msgstr[1] "20x66mm dardos perforantes, casera" +msgstr[2] "20x66mm dardos perforantes, casera" #. ~ Description for {'str': '20x66mm flechette, handmade', 'str_pl': '20x66mm #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Son réplicas falsas de las balas de Rivtech 20x66mm sin casquillo, con una " -"carga de dardos perforantes. Al no tener casquillo, no pueden ser desarmadas" -" ni recargadas." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" msgid_plural "20x66mm buckshot, handmades" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perdigones grandes 20x66mm, casero" +msgstr[1] "perdigones grandes 20x66mm, casero" +msgstr[2] "perdigones grandes 20x66mm, casero" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Son réplicas cutres de las balas de Rivtech 20x66mm sin casquillo. Al no " -"tener casquillo, no pueden ser desarmadas ni recargadas." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" msgid_plural "20x66mm slugs, handmade" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "posta 20x66mm, casera" +msgstr[1] "postas 20x66mm, casera" +msgstr[2] "postas 20x66mm, casera" #. ~ Description for {'str': '20x66mm slug, handmade', 'str_pl': '20x66mm #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Son réplicas falsas de las balas de Rivtech 20x66mm sin casquillo, de " -"proyectil sólido. Al no tener casquillo, no pueden ser desarmadas ni " -"recargadas." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -52987,9 +53188,9 @@ msgstr "" #: data/json/items/ammo/22.json msgid ".22 LR" msgid_plural ".22 LRs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".22 LR" +msgstr[1] ".22 LR" +msgstr[2] ".22 LR" #. ~ Description for {'str': '.22 LR'} #: data/json/items/ammo/22.json @@ -53032,9 +53233,9 @@ msgstr[2] "" #: data/json/items/ammo/22.json msgid ".22 LR, black powder" msgid_plural ".22 LR, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".22 LR, pólvora" +msgstr[1] ".22 LR, pólvora" +msgstr[2] ".22 LR, pólvora" #: data/json/items/ammo/223.json msgid "5.56x45mm '.223 Remington'" @@ -53112,9 +53313,9 @@ msgstr[2] "" #: data/json/items/ammo/270win.json msgid ".270 Winchester JSP" msgid_plural ".270 Winchester JSPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".270 Winchester JSP" +msgstr[1] ".270 Winchester JSP" +msgstr[2] ".270 Winchester JSP" #. ~ Description for {'str': '.270 Winchester JSP'} #: data/json/items/ammo/270win.json @@ -53132,16 +53333,16 @@ msgstr "" #: data/json/items/ammo/270win.json msgid ".270 Winchester JSP, black powder" msgid_plural ".270 Winchester JSP, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".270 Winchester JSP, pólvora" +msgstr[1] ".270 Winchester JSP, pólvora" +msgstr[2] ".270 Winchester JSP, pólvora" #: data/json/items/ammo/300.json msgid ".300 Winchester Magnum" msgid_plural ".300 Winchester Magnums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".300 Winchester Magnum" +msgstr[1] ".300 Winchester Magnum" +msgstr[2] ".300 Winchester Magnum" #. ~ Description for {'str': '.300 Winchester Magnum'} #: data/json/items/ammo/300.json @@ -53159,16 +53360,16 @@ msgstr "" #: data/json/items/ammo/300.json msgid ".300 Winchester Magnum, black powder" msgid_plural ".300 Winchester Magnum, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".300 Winchester Magnum, pólvora" +msgstr[1] ".300 Winchester Magnum, pólvora" +msgstr[2] ".300 Winchester Magnum, pólvora" #: data/json/items/ammo/3006.json msgid ".30-06 Springfield" msgid_plural ".30-06 Springfields" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 Springfield" +msgstr[1] ".30-06 Springfield" +msgstr[2] ".30-06 Springfield" #. ~ Description for {'str': '.30-06 Springfield'} #: data/json/items/ammo/3006.json @@ -53184,9 +53385,9 @@ msgstr "" #: data/json/items/ammo/3006.json msgid ".30-06 M14A1 tracer" msgid_plural ".30-06 M14A1 tracers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 M14A1 trazadora" +msgstr[1] ".30-06 M14A1 trazadoras" +msgstr[2] ".30-06 M14A1 trazadoras" #. ~ Description for {'str': '.30-06 M14A1 tracer'} #: data/json/items/ammo/3006.json @@ -53202,9 +53403,9 @@ msgstr "" #: data/json/items/ammo/3006.json msgid ".30-06 M2 AP" msgid_plural ".30-06 M2 APs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 M2 AP" +msgstr[1] ".30-06 M2 AP" +msgstr[2] ".30-06 M2 AP" #. ~ Description for {'str': '.30-06 M2 AP'} #: data/json/items/ammo/3006.json @@ -53220,16 +53421,16 @@ msgstr "" #: data/json/items/ammo/3006.json msgid ".30-06 Springfield, black powder" msgid_plural ".30-06 Springfield, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 Springfield, pólvora" +msgstr[1] ".30-06 Springfield, pólvora" +msgstr[2] ".30-06 Springfield, pólvora" #: data/json/items/ammo/3006.json msgid ".30-06 Springfield tracer, black powder" msgid_plural ".30-06 Springfield tracer, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 Springfield trazadora, pólvora" +msgstr[1] ".30-06 Springfield trazadoras, pólvora" +msgstr[2] ".30-06 Springfield trazadoras, pólvora" #: data/json/items/ammo/3006.json msgid ".30-06 M2 AP, black powder" @@ -53274,9 +53475,9 @@ msgstr "" #: data/json/items/ammo/300blk.json msgid ".300 AAC Blackout, black powder" msgid_plural ".300 AAC Blackout, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".300 AAC Blackout, pólvora" +msgstr[1] ".300 AAC Blackout, pólvora" +msgstr[2] ".300 AAC Blackout, pólvora" #: data/json/items/ammo/308.json msgid "7.62x51mm '.308 Winchester'" @@ -53316,9 +53517,9 @@ msgstr "" #: data/json/items/ammo/308.json msgid "7.62x51mm NATO tracer" msgid_plural "7.62x51mm NATO tracers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x51mm NATO trazadora" +msgstr[1] "7.62x51mm NATO trazadoras" +msgstr[2] "7.62x51mm NATO trazadoras" #. ~ Description for {'str': '7.62x51mm NATO tracer'} #: data/json/items/ammo/308.json @@ -53353,9 +53554,9 @@ msgstr[2] "" #: data/json/items/ammo/32.json msgid ".32 ACP" msgid_plural ".32 ACPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".32 ACP" +msgstr[1] ".32 ACP" +msgstr[2] ".32 ACP" #. ~ Description for {'str': '.32 ACP'} #: data/json/items/ammo/32.json @@ -53369,16 +53570,16 @@ msgstr "" #: data/json/items/ammo/32.json msgid ".32 ACP, black powder" msgid_plural ".32 ACP, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".32 ACP, pólvora" +msgstr[1] ".32 ACP, pólvora" +msgstr[2] ".32 ACP, pólvora" #: data/json/items/ammo/357mag.json msgid ".357 magnum FMJ" msgid_plural ".357 magnum FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 Magnum FMJ" +msgstr[1] ".357 Magnum FMJ" +msgstr[2] ".357 Magnum FMJ" #. ~ Description for {'str': '.357 magnum FMJ'} #: data/json/items/ammo/357mag.json @@ -53393,9 +53594,9 @@ msgstr "" #: data/json/items/ammo/357mag.json msgid ".357 magnum JHP" msgid_plural ".357 magnum JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 magnum JHP" +msgstr[1] ".357 magnum JHP" +msgstr[2] ".357 magnum JHP" #. ~ Description for {'str': '.357 magnum JHP'} #: data/json/items/ammo/357mag.json @@ -53410,23 +53611,23 @@ msgstr "" #: data/json/items/ammo/357mag.json msgid ".357 Magnum FMJ, black powder" msgid_plural ".357 Magnum FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 Magnum FMJ, pólvora" +msgstr[1] ".357 Magnum FMJ, pólvora" +msgstr[2] ".357 Magnum FMJ, pólvora" #: data/json/items/ammo/357mag.json msgid ".357 Magnum JHP, black powder" msgid_plural ".357 Magnum JHP, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 Magnum JHP, pólvora" +msgstr[1] ".357 Magnum JHP, pólvora" +msgstr[2] ".357 Magnum JHP, pólvora" #: data/json/items/ammo/357sig.json msgid ".357 SIG FMJ" msgid_plural ".357 SIG FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 SIG FMJ" +msgstr[1] ".357 SIG FMJ" +msgstr[2] ".357 SIG FMJ" #. ~ Description for {'str': '.357 SIG FMJ'} #: data/json/items/ammo/357sig.json @@ -53440,9 +53641,9 @@ msgstr "" #: data/json/items/ammo/357sig.json msgid ".357 SIG JHP" msgid_plural ".357 SIG JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 SIG JHP" +msgstr[1] ".357 SIG JHP" +msgstr[2] ".357 SIG JHP" #. ~ Description for {'str': '.357 SIG JHP'} #: data/json/items/ammo/357sig.json @@ -53474,9 +53675,9 @@ msgstr "" #: data/json/items/ammo/38.json msgid ".38 FMJ" msgid_plural ".38 FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 FMJ" +msgstr[1] ".38 FMJ" +msgstr[2] ".38 FMJ" #. ~ Description for {'str': '.38 FMJ'} #: data/json/items/ammo/38.json @@ -53490,9 +53691,9 @@ msgstr "" #: data/json/items/ammo/38.json msgid ".38 Special" msgid_plural ".38 Specials" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 Special" +msgstr[1] ".38 Special" +msgstr[2] ".38 Special" #. ~ Description for {'str': '.38 Special'} #: data/json/items/ammo/38.json @@ -53506,23 +53707,23 @@ msgstr "" #: data/json/items/ammo/38.json msgid ".38 FMJ, black powder" msgid_plural ".38 FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 FMJ, pólvora" +msgstr[1] ".38 FMJ, pólvora" +msgstr[2] ".38 FMJ, pólvora" #: data/json/items/ammo/38.json msgid ".38 Special, black powder" msgid_plural ".38 Special, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 Special, pólvora" +msgstr[1] ".38 Special, pólvora" +msgstr[2] ".38 Special, pólvora" #: data/json/items/ammo/380.json msgid ".380 ACP FMJ" msgid_plural ".380 ACP FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP FMJ" +msgstr[1] ".380 ACP FMJ" +msgstr[2] ".380 ACP FMJ" #. ~ Description for {'str': '.380 ACP FMJ'} #: data/json/items/ammo/380.json @@ -53539,9 +53740,9 @@ msgstr "" #: data/json/items/ammo/380.json msgid ".380 ACP JHP" msgid_plural ".380 ACP JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP JHP" +msgstr[1] ".380 ACP JHP" +msgstr[2] ".380 ACP JHP" #. ~ Description for {'str': '.380 ACP JHP'} #: data/json/items/ammo/380.json @@ -53558,9 +53759,9 @@ msgstr "" #: data/json/items/ammo/380.json msgid ".380 ACP +P" msgid_plural ".380 ACP +Ps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP +P" +msgstr[1] ".380 ACP +P" +msgstr[2] ".380 ACP +P" #. ~ Description for {'str': '.380 ACP +P'} #: data/json/items/ammo/380.json @@ -53578,23 +53779,23 @@ msgstr "" #: data/json/items/ammo/380.json msgid ".380 ACP FMJ, black powder" msgid_plural ".380 ACP FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP FMJ, pólvora" +msgstr[1] ".380 ACP FMJ, pólvora" +msgstr[2] ".380 ACP FMJ, pólvora" #: data/json/items/ammo/380.json msgid ".380 ACP JHP, black powder" msgid_plural ".380 ACP JHP, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP JHP, pólvora" +msgstr[1] ".380 ACP JHP, pólvora" +msgstr[2] ".380 ACP JHP, pólvora" #: data/json/items/ammo/38super.json msgid ".38 Super FMJ" msgid_plural ".38 Super FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 Super FMJ" +msgstr[1] ".38 Super FMJ" +msgstr[2] ".38 Super FMJ" #. ~ Description for {'str': '.38 Super FMJ'} #: data/json/items/ammo/38super.json @@ -53619,9 +53820,9 @@ msgstr "" #: data/json/items/ammo/40.json msgid ".40 S&W FMJ" msgid_plural ".40 S&W FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".40 S&W FMJ" +msgstr[1] ".40 S&W FMJ" +msgstr[2] ".40 S&W FMJ" #. ~ Description for {'str': '.40 S&W FMJ'} #: data/json/items/ammo/40.json @@ -53637,9 +53838,9 @@ msgstr "" #: data/json/items/ammo/40.json msgid ".40 S&W JHP" msgid_plural ".40 S&W JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".40 S&W JHP" +msgstr[1] ".40 S&W JHP" +msgstr[2] ".40 S&W JHP" #. ~ Description for {'str': '.40 S&W JHP'} #: data/json/items/ammo/40.json @@ -53655,16 +53856,16 @@ msgstr "" #: data/json/items/ammo/40.json msgid ".40 S&W FMJ, black powder" msgid_plural ".40 S&W FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".40 S&W FMJ, pólvora" +msgstr[1] ".40 S&W FMJ, pólvora" +msgstr[2] ".40 S&W FMJ, pólvora" #: data/json/items/ammo/40.json msgid ".40 S&W JHP, black powder" msgid_plural ".40 S&W JHP, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".40 S&W JHP, pólvora" +msgstr[1] ".40 S&W JHP, pólvora" +msgstr[2] ".40 S&W JHP, pólvora" #: data/json/items/ammo/40x46mm.json msgid "40x46mm M1006 stun" @@ -53854,9 +54055,9 @@ msgstr "" #: data/json/items/ammo/410shot.json msgid ".410 000 shot" msgid_plural ".410 000 shots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho .410 000" +msgstr[1] "cartuchos .410 000" +msgstr[2] "cartuchos .410 000" #. ~ Description for {'str': '.410 000 shot'} #: data/json/items/ammo/410shot.json @@ -53867,9 +54068,9 @@ msgstr "" #: data/json/items/ammo/44.json msgid ".44 Magnum FMJ" msgid_plural ".44 Magnum FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".44 Magnum FMJ" +msgstr[1] ".44 Magnum FMJ" +msgstr[2] ".44 Magnum FMJ" #. ~ Description for {'str': '.44 Magnum FMJ'} #: data/json/items/ammo/44.json @@ -53881,9 +54082,9 @@ msgstr "" #: data/json/items/ammo/44.json msgid ".44 Magnum" msgid_plural ".44 Magnums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".44 Magnum" +msgstr[1] ".44 Magnum" +msgstr[2] ".44 Magnum" #. ~ Description for {'str': '.44 Magnum'} #: data/json/items/ammo/44.json @@ -53900,16 +54101,16 @@ msgstr "" #: data/json/items/ammo/44.json msgid ".44 Magnum, black powder" msgid_plural ".44 Magnum, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".44 Magnum, pólvora" +msgstr[1] ".44 Magnum, pólvora" +msgstr[2] ".44 Magnum, pólvora" #: data/json/items/ammo/44.json msgid ".44 Magnum FMJ, black powder" msgid_plural ".44 Magnum FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".44 Magnum FMJ, pólvora" +msgstr[1] ".44 Magnum FMJ, pólvora" +msgstr[2] ".44 Magnum FMJ, pólvora" #: data/json/items/ammo/44paper.json msgid ".44 paper cartridge" @@ -53930,9 +54131,9 @@ msgstr "" #: data/json/items/ammo/45.json msgid ".45 ACP FMJ" msgid_plural ".45 ACP FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 ACP FMJ" +msgstr[1] ".45 ACP FMJ" +msgstr[2] ".45 ACP FMJ" #. ~ Description for {'str': '.45 ACP FMJ'} #: data/json/items/ammo/45.json @@ -53946,9 +54147,9 @@ msgstr "" #: data/json/items/ammo/45.json msgid ".45 ACP JHP" msgid_plural ".45 ACP JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 ACP JHP" +msgstr[1] ".45 ACP JHP" +msgstr[2] ".45 ACP JHP" #. ~ Description for {'str': '.45 ACP JHP'} #: data/json/items/ammo/45.json @@ -53964,9 +54165,9 @@ msgstr "" #: data/json/items/ammo/45.json msgid ".45 ACP +P" msgid_plural ".45 ACP +Ps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 ACP +P" +msgstr[1] ".45 ACP +P" +msgstr[2] ".45 ACP +P" #. ~ Description for {'str': '.45 ACP +P'} #: data/json/items/ammo/45.json @@ -53982,23 +54183,23 @@ msgstr "" #: data/json/items/ammo/45.json msgid ".45 ACP FMJ, black powder" msgid_plural ".45 ACP FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 ACP FMJ, pólvora" +msgstr[1] ".45 ACP FMJ, pólvora" +msgstr[2] ".45 ACP FMJ, pólvora" #: data/json/items/ammo/45.json msgid ".45 ACP JHP, black powder" msgid_plural ".45 ACP JHP, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 ACP JHP, pólvora" +msgstr[1] ".45 ACP JHP, pólvora" +msgstr[2] ".45 ACP JHP, pólvora" #: data/json/items/ammo/454.json msgid ".454 Casull" msgid_plural ".454 Casulls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".454 Casull" +msgstr[1] ".454 Casull" +msgstr[2] ".454 Casull" #. ~ Description for {'str': '.454 Casull'} #: data/json/items/ammo/454.json @@ -54018,16 +54219,16 @@ msgstr "" #: data/json/items/ammo/454.json msgid ".454 Casull, black powder" msgid_plural ".454 Casull, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".454 Casull, pólvora" +msgstr[1] ".454 Casull, pólvora" +msgstr[2] ".454 Casull, pólvora" #: data/json/items/ammo/4570.json msgid ".45-70 SP" msgid_plural ".45-70 SPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45-70 SP" +msgstr[1] ".45-70 SP" +msgstr[2] ".45-70 SP" #. ~ Description for {'str': '.45-70 SP'} #: data/json/items/ammo/4570.json @@ -54043,9 +54244,9 @@ msgstr "" #: data/json/items/ammo/4570.json msgid ".45-70 +P penetrator" msgid_plural ".45-70 +P penetrators" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45-70 +P perforante" +msgstr[1] ".45-70 +P perforante" +msgstr[2] ".45-70 +P perforante" #. ~ Description for {'str': '.45-70 +P penetrator'} #: data/json/items/ammo/4570.json @@ -54061,9 +54262,9 @@ msgstr "" #: data/json/items/ammo/4570.json msgid ".45-70 LFN cowboy" msgid_plural ".45-70 LFN cowboys" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45-70 LFN cowboy" +msgstr[1] ".45-70 LFN cowboy" +msgstr[2] ".45-70 LFN cowboy" #. ~ Description for {'str': '.45-70 LFN cowboy'} #: data/json/items/ammo/4570.json @@ -54079,9 +54280,9 @@ msgstr "" #: data/json/items/ammo/4570.json msgid ".45-70, black powder" msgid_plural ".45-70, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45-70, pólvora" +msgstr[1] ".45-70, pólvora" +msgstr[2] ".45-70, pólvora" #. ~ Description for {'str': '.45-70, black powder'} #: data/json/items/ammo/4570.json @@ -54099,9 +54300,9 @@ msgstr "" #: data/json/items/ammo/45colt.json msgid ".45 Colt JHP" msgid_plural ".45 Colt JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 Colt JHP" +msgstr[1] ".45 Colt JHP" +msgstr[2] ".45 Colt JHP" #. ~ Description for {'str': '.45 Colt JHP'} #: data/json/items/ammo/45colt.json @@ -54126,9 +54327,9 @@ msgstr[2] "" #: data/json/items/ammo/46.json msgid "4.6x30mm" msgid_plural "4.6x30mms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "4.6x30mm" +msgstr[1] "4.6x30mm" +msgstr[2] "4.6x30mm" #. ~ Description for {'str': '4.6x30mm'} #: data/json/items/ammo/46.json @@ -54144,9 +54345,9 @@ msgstr "" #: data/json/items/ammo/46.json msgid "4.6x30mm, black powder" msgid_plural "4.6x30mm, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "4.6x30mm, pólvora" +msgstr[1] "4.6x30mm, pólvora" +msgstr[2] "4.6x30mm, pólvora" #. ~ Description for {'str': '4.6x30mm, black powder'} #. ~ Description for {'str': '4.6x30mm, reloaded'} @@ -54166,9 +54367,9 @@ msgstr "" #: data/json/items/ammo/460.json msgid ".460 Rowland HCFN" msgid_plural ".460 Rowland HCFNs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".460 Rowland HCFN" +msgstr[1] ".460 Rowland HCFN" +msgstr[2] ".460 Rowland HCFN" #. ~ Description for {'str': '.460 Rowland HCFN'} #: data/json/items/ammo/460.json @@ -54182,9 +54383,9 @@ msgstr "" #: data/json/items/ammo/460.json msgid ".460 Rowland" msgid_plural ".460 Rowlands" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".460 Rowland" +msgstr[1] ".460 Rowland" +msgstr[2] ".460 Rowland" #. ~ Description for {'str': '.460 Rowland'} #: data/json/items/ammo/460.json @@ -54204,23 +54405,23 @@ msgstr "" #: data/json/items/ammo/460.json msgid ".460 Rowland FMJ, black powder" msgid_plural ".460 Rowland FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".460 Rowland FMJ, pólvora" +msgstr[1] ".460 Rowland FMJ, pólvora" +msgstr[2] ".460 Rowland FMJ, pólvora" #: data/json/items/ammo/460.json msgid ".460 Rowland, black powder" msgid_plural ".460 Rowland, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".460 Rowland, pólvora" +msgstr[1] ".460 Rowland, pólvora" +msgstr[2] ".460 Rowland, pólvora" #: data/json/items/ammo/50.json msgid ".50 BMG M17 tracer" msgid_plural ".50 BMG M17 tracers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG M17 trazadora" +msgstr[1] ".50 BMG M17 trazadoras" +msgstr[2] ".50 BMG M17 trazadoras" #. ~ Description for {'str': '.50 BMG M17 tracer'} #: data/json/items/ammo/50.json @@ -54236,9 +54437,9 @@ msgstr "" #: data/json/items/ammo/50.json msgid ".50 BMG M33 Ball" msgid_plural ".50 BMG M33 Balls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG M33 Bola" +msgstr[1] ".50 BMG M33 Bola" +msgstr[2] ".50 BMG M33 Bola" #. ~ Description for {'str': '.50 BMG M33 Ball'} #: data/json/items/ammo/50.json @@ -54258,9 +54459,9 @@ msgstr "" #: data/json/items/ammo/50.json msgid ".50 BMG Match" msgid_plural ".50 BMG Matches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG Match" +msgstr[1] ".50 BMG Match" +msgstr[2] ".50 BMG Match" #. ~ Description for {'str': '.50 BMG Match', 'str_pl': '.50 BMG Matches'} #: data/json/items/ammo/50.json @@ -54274,9 +54475,9 @@ msgstr "" #: data/json/items/ammo/50.json msgid ".50 BMG M2 AP" msgid_plural ".50 BMG M2 APs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG M2 AP" +msgstr[1] ".50 BMG M2 AP" +msgstr[2] ".50 BMG M2 AP" #. ~ Description for {'str': '.50 BMG M2 AP'} #: data/json/items/ammo/50.json @@ -54290,9 +54491,9 @@ msgstr "" #: data/json/items/ammo/50.json msgid ".50 BMG Raufoss Mk 211" msgid_plural ".50 BMG Raufoss Mk 211s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG Raufoss Mk 211" +msgstr[1] ".50 BMG Raufoss Mk 211" +msgstr[2] ".50 BMG Raufoss Mk 211" #. ~ Description for {'str': '.50 BMG Raufoss Mk 211'} #: data/json/items/ammo/50.json @@ -54318,9 +54519,9 @@ msgstr "" #: data/json/items/ammo/500.json msgid ".500 S&W Magnum" msgid_plural ".500 S&W Magnums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".500 S&W Magnum" +msgstr[1] ".500 S&W Magnum" +msgstr[2] ".500 S&W Magnum" #. ~ Description for {'str': '.500 S&W Magnum'} #: data/json/items/ammo/500.json @@ -54337,16 +54538,16 @@ msgstr "" #: data/json/items/ammo/500.json msgid ".500 S&W Magnum, black powder" msgid_plural ".500 S&W Magnum, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".500 S&W Magnum, pólvora" +msgstr[1] ".500 S&W Magnum, pólvora" +msgstr[2] ".500 S&W Magnum, pólvora" #: data/json/items/ammo/545x39.json msgid "5.45x39mm 7N10" msgid_plural "5.45x39mm 7N10s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5.45x39mm 7N10" +msgstr[1] "5.45x39mm 7N10" +msgstr[2] "5.45x39mm 7N10" #. ~ Description for {'str': '5.45x39mm 7N10'} #: data/json/items/ammo/545x39.json @@ -54363,9 +54564,9 @@ msgstr "" #: data/json/items/ammo/545x39.json msgid "5.45x39mm 7N22" msgid_plural "5.45x39mm 7N22s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5.45x39mm 7N22" +msgstr[1] "5.45x39mm 7N22" +msgstr[2] "5.45x39mm 7N22" #. ~ Description for {'str': '5.45x39mm 7N22'} #: data/json/items/ammo/545x39.json @@ -54379,9 +54580,9 @@ msgstr "" #: data/json/items/ammo/57.json msgid "5.7x28mm SS190" msgid_plural "5.7x28mm SS190s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5.7x28mm SS190" +msgstr[1] "5.7x28mm SS190" +msgstr[2] "5.7x28mm SS190" #. ~ Description for {'str': '5.7x28mm SS190'} #: data/json/items/ammo/57.json @@ -54403,9 +54604,9 @@ msgstr "" #: data/json/items/ammo/57.json msgid "5.7x28mm, black powder" msgid_plural "5.7x28mm, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5.7x28mm, pólvora" +msgstr[1] "5.7x28mm, pólvora" +msgstr[2] "5.7x28mm, pólvora" #. ~ Description for {'str': '5.7x28mm, black powder'} #. ~ Description for {'str': '5.7x28mm, reloaded'} @@ -54465,9 +54666,9 @@ msgstr "" #: data/json/items/ammo/66mm.json msgid "M74 rocket" msgid_plural "M74 rockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil M74" +msgstr[1] "misiles M74" +msgstr[2] "misiles M74" #. ~ Description for {'str': 'M74 rocket'} #: data/json/items/ammo/66mm.json @@ -54498,9 +54699,9 @@ msgstr "" #: data/json/items/ammo/700nx.json msgid ".700 NX" msgid_plural ".700 NXs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".700 NX" +msgstr[1] ".700 NX" +msgstr[2] ".700 NX" #. ~ Description for {'str': '.700 NX'} #: data/json/items/ammo/700nx.json @@ -54518,9 +54719,9 @@ msgstr "" #: data/json/items/ammo/762.json msgid "7.62x39mm 57-N-231" msgid_plural "7.62x39mm 57-N-231s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x39mm 57-N-231" +msgstr[1] "7.62x39mm 57-N-231" +msgstr[2] "7.62x39mm 57-N-231" #. ~ Description for {'str': '7.62x39mm 57-N-231'} #: data/json/items/ammo/762.json @@ -54539,9 +54740,9 @@ msgstr "" #: data/json/items/ammo/762.json msgid "7.62x39mm M67" msgid_plural "7.62x39mm M67s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x39mm M67" +msgstr[1] "7.62x39mm M67" +msgstr[2] "7.62x39mm M67" #. ~ Description for {'str': '7.62x39mm M67'} #: data/json/items/ammo/762.json @@ -54559,9 +54760,9 @@ msgstr "" #: data/json/items/ammo/762R.json msgid "7.62x54mmR" msgid_plural "7.62x54mmRs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x54mmR" +msgstr[1] "7.62x54mmR" +msgstr[2] "7.62x54mmR" #. ~ Description for {'str': '7.62x54mmR'} #: data/json/items/ammo/762R.json @@ -54615,9 +54816,9 @@ msgstr "" #: data/json/items/ammo/762x25.json msgid "7.62x25mm Type P" msgid_plural "7.62x25mm Type Ps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x25mm Tipo P" +msgstr[1] "7.62x25mm Tipo P" +msgstr[2] "7.62x25mm Tipo P" #. ~ Description for {'str': '7.62x25mm Type P'} #: data/json/items/ammo/762x25.json @@ -54633,16 +54834,16 @@ msgstr "" #: data/json/items/ammo/762x25.json msgid "7.62x25mm FMJ, black powder" msgid_plural "7.62x25mm FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x25mm FMJ, pólvora" +msgstr[1] "7.62x25mm FMJ, pólvora" +msgstr[2] "7.62x25mm FMJ, pólvora" #: data/json/items/ammo/84x246mm.json msgid "84x246mm HE rocket" msgid_plural "84x246mm HE rockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil 84x246mm HE" +msgstr[1] "misiles 84x246mm HE" +msgstr[2] "misiles 84x246mm HE" #. ~ Description for {'str': '84x246mm HE rocket'} #: data/json/items/ammo/84x246mm.json @@ -54657,9 +54858,9 @@ msgstr "" #: data/json/items/ammo/84x246mm.json msgid "84x246mm HEDP rocket" msgid_plural "84x246mm HEDP rockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil 84x246mm HEDP" +msgstr[1] "misiles 84x246mm HEDP" +msgstr[2] "misiles 84x246mm HEDP" #. ~ Description for {'str': '84x246mm HEDP rocket'} #: data/json/items/ammo/84x246mm.json @@ -54675,9 +54876,9 @@ msgstr "" #: data/json/items/ammo/84x246mm.json msgid "84x246mm smoke rocket" msgid_plural "84x246mm smoke rockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil fumígeno 84x246mm" +msgstr[1] "misiles fumígenos 84x246mm" +msgstr[2] "misiles fumígenos 84x246mm" #. ~ Description for {'str': '84x246mm smoke rocket'} #: data/json/items/ammo/84x246mm.json @@ -54691,20 +54892,60 @@ msgstr "" "los movimientos de las tropas." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"Son unas réplicas falsas de las balas 8x40mm sin casquillo de Rivtech. Al no" -" tener casquillo, no pueden ser desarmadas ni recargadas." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -54718,9 +54959,9 @@ msgstr "" #: data/json/items/ammo/8x40mm.json msgid "8x40mm sporting" msgid_plural "8x40mm sportings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "8x40mm deportiva" +msgstr[1] "8x40mm deportivas" +msgstr[2] "8x40mm deportivas" #. ~ Description for {'str': '8x40mm sporting'} #: data/json/items/ammo/8x40mm.json @@ -54736,9 +54977,9 @@ msgstr "" #: data/json/items/ammo/8x40mm.json msgid "8x40mm HVP" msgid_plural "8x40mm HVPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "8x40mm HVP" +msgstr[1] "8x40mm HVP" +msgstr[2] "8x40mm HVP" #. ~ Description for {'str': '8x40mm HVP'} #: data/json/items/ammo/8x40mm.json @@ -54755,9 +54996,9 @@ msgstr "" #: data/json/items/ammo/8x40mm.json msgid "8x40mm tracer" msgid_plural "8x40mm tracers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "8x40mm trazadora" +msgstr[1] "8x40mm trazadoras" +msgstr[2] "8x40mm trazadoras" #. ~ Description for {'str': '8x40mm tracer'} #: data/json/items/ammo/8x40mm.json @@ -54775,9 +55016,9 @@ msgstr "" #: data/json/items/ammo/8x40mm.json msgid "8x40mm JHP" msgid_plural "8x40mm JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "8x40mm JHP" +msgstr[1] "8x40mm JHP" +msgstr[2] "8x40mm JHP" #. ~ Description for {'str': '8x40mm JHP'} #: data/json/items/ammo/8x40mm.json @@ -54793,9 +55034,9 @@ msgstr "" #: data/json/items/ammo/9mm.json msgid "9x19mm JHP" msgid_plural "9x19mm JHPs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm JHP" +msgstr[1] "9x19mm JHP" +msgstr[2] "9x19mm JHP" #. ~ Description for {'str': '9x19mm JHP'} #: data/json/items/ammo/9mm.json @@ -54813,9 +55054,9 @@ msgstr "" #: data/json/items/ammo/9mm.json msgid "9x19mm FMJ" msgid_plural "9x19mm FMJs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm FMJ" +msgstr[1] "9x19mm FMJ" +msgstr[2] "9x19mm FMJ" #. ~ Description for {'str': '9x19mm FMJ'} #: data/json/items/ammo/9mm.json @@ -54830,9 +55071,9 @@ msgstr "" #: data/json/items/ammo/9mm.json msgid "9x19mm +P" msgid_plural "9x19mm +Ps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm +P" +msgstr[1] "9x19mm +P" +msgstr[2] "9x19mm +P" #. ~ Description for {'str': '9x19mm +P'} #: data/json/items/ammo/9mm.json @@ -54847,9 +55088,9 @@ msgstr "" #: data/json/items/ammo/9mm.json msgid "9x19mm +P+" msgid_plural "9x19mm +P+s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm +P+" +msgstr[1] "9x19mm +P+" +msgstr[2] "9x19mm +P+" #. ~ Description for {'str': '9x19mm +P+'} #: data/json/items/ammo/9mm.json @@ -54863,23 +55104,23 @@ msgstr "" #: data/json/items/ammo/9mm.json msgid "9x19mm JHP, black powder" msgid_plural "9x19mm JHP, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm JHP, pólvora" +msgstr[1] "9x19mm JHP, pólvora" +msgstr[2] "9x19mm JHP, pólvora" #: data/json/items/ammo/9mm.json msgid "9x19mm FMJ, black powder" msgid_plural "9x19mm FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm FMJ, pólvora" +msgstr[1] "9x19mm FMJ, pólvora" +msgstr[2] "9x19mm FMJ, pólvora" #: data/json/items/ammo/9x18.json msgid "9x18mm 57-N-181S" msgid_plural "9x18mm 57-N-181Ss" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm 57-N-181S" +msgstr[1] "9x18mm 57-N-181S" +msgstr[2] "9x18mm 57-N-181S" #. ~ Description for {'str': '9x18mm 57-N-181S'} #: data/json/items/ammo/9x18.json @@ -54895,9 +55136,9 @@ msgstr "" #: data/json/items/ammo/9x18.json msgid "9x18mm SP-7" msgid_plural "9x18mm SP-7s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm SP-7" +msgstr[1] "9x18mm SP-7" +msgstr[2] "9x18mm SP-7" #. ~ Description for {'str': '9x18mm SP-7'} #: data/json/items/ammo/9x18.json @@ -54913,9 +55154,9 @@ msgstr "" #: data/json/items/ammo/9x18.json msgid "9x18mm RG028" msgid_plural "9x18mm RG028s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm RG028" +msgstr[1] "9x18mm RG028" +msgstr[2] "9x18mm RG028" #. ~ Description for {'str': '9x18mm RG028'} #: data/json/items/ammo/9x18.json @@ -54929,23 +55170,23 @@ msgstr "" #: data/json/items/ammo/9x18.json msgid "9x18mm, black powder" msgid_plural "9x18mm, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm, pólvora" +msgstr[1] "9x18mm, pólvora" +msgstr[2] "9x18mm, pólvora" #: data/json/items/ammo/9x18.json msgid "9x18mm FMJ, black powder" msgid_plural "9x18mm FMJ, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm FMJ, pólvora" +msgstr[1] "9x18mm FMJ, pólvora" +msgstr[2] "9x18mm FMJ, pólvora" #: data/json/items/ammo/atgm.json msgid "152mm ATGM HEAT" msgid_plural "152mm ATGM HEATs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "152mm ATGM HEAT" +msgstr[1] "152mm ATGM HEAT" +msgstr[2] "152mm ATGM HEAT" #. ~ Description for {'str': '152mm ATGM HEAT'} #: data/json/items/ammo/atgm.json @@ -54960,9 +55201,9 @@ msgstr "" #: data/json/items/ammo/barb.json msgid "paralyzing barb" msgid_plural "paralyzing barbs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pincho paralizante" +msgstr[1] "pinchos paralizantes" +msgstr[2] "pinchos paralizantes" #. ~ Description for {'str': 'paralyzing barb'} #: data/json/items/ammo/barb.json @@ -54976,9 +55217,9 @@ msgstr "" #: data/json/items/ammo/chemical_spray.json msgid "sprayable toxic gas" msgid_plural "sprayable toxic gas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gas tóxico en aerosol" +msgstr[1] "gas tóxico en aerosol" +msgstr[2] "gas tóxico en aerosol" #. ~ Description for {'str_sp': 'sprayable toxic gas'} #: data/json/items/ammo/chemical_spray.json @@ -54993,9 +55234,9 @@ msgstr "" #: data/json/items/ammo/chemical_spray.json msgid "sprayable fungicide" msgid_plural "sprayable fungicide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fungicida en aerosol" +msgstr[1] "fungicida en aerosol" +msgstr[2] "fungicida en aerosol" #. ~ Description for {'str_sp': 'sprayable fungicide'} #: data/json/items/ammo/chemical_spray.json @@ -55010,9 +55251,9 @@ msgstr "" #: data/json/items/ammo/chemical_spray.json msgid "sprayable insecticide" msgid_plural "sprayable insecticide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "insecticida en aerosol" +msgstr[1] "insecticida en aerosol" +msgstr[2] "insecticida en aerosol" #. ~ Description for {'str_sp': 'sprayable insecticide'} #: data/json/items/ammo/chemical_spray.json @@ -55038,9 +55279,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "paper shot cartridge" msgid_plural "paper shot cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de papel de escopeta" +msgstr[1] "cartuchos de papel de escopeta" +msgstr[2] "cartuchos de papel de escopeta" #. ~ Description for {'str': 'paper shot cartridge'} #: data/json/items/ammo/flintlock.json @@ -55091,9 +55332,9 @@ msgstr "" #: data/json/items/ammo/nail.json msgid "flechette" msgid_plural "flechettes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dardo perforante" +msgstr[1] "dardos perforantes" +msgstr[2] "dardos perforantes" #. ~ Description for {'str': 'flechette'} #: data/json/items/ammo/nail.json @@ -55126,49 +55367,49 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "Un tubo de bolas de paintball. Virtualmente no hacen daño." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Es munición 93mm monoetapa de alta explosividad para el RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "Es munición 64mm/105mm de alta explosividad para el RPG-7." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "Es munición termobárica 105mm para el RPG-7." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -55177,37 +55418,37 @@ msgstr "Es munición antipersonal 40mm de alta explosividad para el RPG-7." #: data/json/items/ammo/shot.json msgid "birdshot, black powder" msgid_plural "birdshot, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perdigones pequeños, pólvora" +msgstr[1] "perdigones pequeños, pólvora" +msgstr[2] "perdigones pequeños, pólvora" #: data/json/items/ammo/shot.json msgid "dragon's breath shell, black powder" msgid_plural "dragon's breath shell, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho aliento de dragón, pólvora" +msgstr[1] "cartuchos aliento de dragón, pólvora" +msgstr[2] "cartuchos aliento de dragón, pólvora" #: data/json/items/ammo/shot.json msgid "00 shot, black powder" msgid_plural "00 shot, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho 00, pólvora" +msgstr[1] "cartuchos 00, pólvora" +msgstr[2] "cartuchos 00, pólvora" #: data/json/items/ammo/shot.json msgid "flechette shell, black powder" msgid_plural "flechette shell, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de dardos perforantes, pólvora" +msgstr[1] "cartuchos de dardos perforantes, pólvora" +msgstr[2] "cartuchos de dardos perforantes, pólvora" #: data/json/items/ammo/shot.json msgid "shotgun slug, black powder" msgid_plural "shotgun slug, black powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "posta de escopeta, pólvora" +msgstr[1] "postas de escopeta, pólvora" +msgstr[2] "postas de escopeta, pólvora" #: data/json/items/ammo/shot.json msgid "00 shot" @@ -55261,9 +55502,9 @@ msgstr "" #: data/json/items/ammo/shot.json msgid "dragon's breath shell" msgid_plural "dragon's breath shells" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho aliento de dragón" +msgstr[1] "cartuchos aliento de dragón" +msgstr[2] "cartuchos aliento de dragón" #. ~ Description for {'str': "dragon's breath shell"} #: data/json/items/ammo/shot.json @@ -55316,9 +55557,9 @@ msgstr "" #: data/json/items/ammo/shot.json msgid "00 shot, scrap loaded" msgid_plural "00 shot, scrap loadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho 00, con chatarra" +msgstr[1] "cartuchos 00, con chatarra" +msgstr[2] "cartuchos 00, con chatarra" #. ~ Description for {'str': '00 shot, scrap loaded'} #. ~ Description for {'str_sp': 'shotshell, junk'} @@ -55334,9 +55575,9 @@ msgstr "" #: data/json/items/ammo/shot.json msgid "00 shot, black powder, scrap loaded" msgid_plural "00 shot, black powder, scrap loadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho 00, pólvora, con chatarra" +msgstr[1] "cartuchos 00, pólvora, con chatarra" +msgstr[2] "cartuchos 00, pólvora, con chatarra" #: data/json/items/ammo/shot.json msgid "shotgun slug" @@ -55357,9 +55598,9 @@ msgstr "" #: data/json/items/ammo/shotpaper.json msgid "birdshot paper cartridge" msgid_plural "birdshot paper cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de papel de perdigones pequeños" +msgstr[1] "cartuchos de papel de perdigones pequeños" +msgstr[2] "cartuchos de papel de perdigones pequeños" #. ~ Description for {'str': 'birdshot paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -55374,9 +55615,9 @@ msgstr "" #: data/json/items/ammo/shotpaper.json msgid "pyrotechnic paper cartridge" msgid_plural "pyrotechnic paper cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de papel pirotécnico" +msgstr[1] "cartuchos de papel pirotécnico" +msgstr[2] "cartuchos de papel pirotécnico" #. ~ Description for {'str': 'pyrotechnic paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -55392,9 +55633,9 @@ msgstr "" #: data/json/items/ammo/shotpaper.json msgid "buckshot paper cartridge" msgid_plural "buckshot paper cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de papel de perdigones grandes" +msgstr[1] "cartuchos de papel de perdigones grandes" +msgstr[2] "cartuchos de papel de perdigones grandes" #. ~ Description for {'str': 'buckshot paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -55408,9 +55649,9 @@ msgstr "" #: data/json/items/ammo/shotpaper.json msgid ".62 paper cartridge" msgid_plural ".62 paper cartridges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de papel .62" +msgstr[1] "cartuchos de papel .62" +msgstr[2] "cartuchos de papel .62" #. ~ Description for {'str': '.62 paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -55433,9 +55674,9 @@ msgstr "" #: data/json/items/ammo/weldgas.json msgid "oxyacetylene" msgid_plural "oxyacetylenes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "oxiacetileno" +msgstr[1] "oxiacetileno" +msgstr[2] "oxiacetileno" #. ~ Description for {'str': 'oxyacetylene'} #: data/json/items/ammo/weldgas.json @@ -55450,9 +55691,9 @@ msgstr "" #: data/mods/Generic_Guns/bandoliers/bandolier.json msgid "ammo pouch" msgid_plural "ammo pouches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de munición" +msgstr[1] "bolsas de munición" +msgstr[2] "bolsas de munición" #. ~ Description for {'str': 'ammo pouch', 'str_pl': 'ammo pouches'} #: data/json/items/armor/ammo_pouch.json @@ -55567,9 +55808,9 @@ msgstr "" #: data/json/items/armor/ammo_pouch.json msgid "chest rig" msgid_plural "chest rig" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tirador utilitario" +msgstr[1] "tirador utilitario" +msgstr[2] "tirador utilitario" #. ~ Description for {'str_sp': 'chest rig'} #: data/json/items/armor/ammo_pouch.json @@ -55797,9 +56038,9 @@ msgstr "" #: data/json/items/armor/ammo_pouch.json msgid "tac vest" msgid_plural "tac vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco táctico" +msgstr[1] "chalecos tácticos" +msgstr[2] "chalecos tácticos" #. ~ Description for {'str': 'tac vest'} #: data/json/items/armor/ammo_pouch.json @@ -55818,9 +56059,9 @@ msgstr "" #: data/json/items/armor/ammo_pouch.json msgid "XL Kevlar vest" msgid_plural "XL Kevlar vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco XL de Kevlar" +msgstr[1] "chalecos XL de Kevlar" +msgstr[2] "chalecos XL de Kevlar" #. ~ Description for {'str': 'XL Kevlar vest'} #: data/json/items/armor/ammo_pouch.json @@ -56064,9 +56305,9 @@ msgstr "" #: data/json/items/armor/ballistic_armor.json msgid "lamellar Kevlar vest" msgid_plural "lamellar Kevlar vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco de Kevlar lamelar" +msgstr[1] "chalecos de Kevlar lamelar" +msgstr[2] "chalecos de Kevlar lamelar" #. ~ Description for {'str': 'lamellar Kevlar vest'} #: data/json/items/armor/ballistic_armor.json @@ -56112,9 +56353,9 @@ msgstr "Son unas bandoleras de cuero para tener a mano cartuchos de rifle." #: data/mods/Generic_Guns/bandoliers/bandolier.json msgid "waist shotgun bandolier" msgid_plural "waist shotgun bandoliers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "canana de escopeta para cintura" +msgstr[1] "cananas de escopeta para cintura" +msgstr[2] "cananas de escopeta para cintura" #. ~ Description for {'str': 'waist shotgun bandolier'} #: data/json/items/armor/bandolier.json @@ -56129,9 +56370,9 @@ msgstr "" #: data/mods/Generic_Guns/bandoliers/bandolier.json msgid "torso shotgun bandolier" msgid_plural "torso shotgun bandoliers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "canana de escopeta para torso" +msgstr[1] "cananas de escopeta para torso" +msgstr[2] "cananas de escopeta para torso" #. ~ Description for {'str': 'torso shotgun bandolier'} #: data/json/items/armor/bandolier.json @@ -56197,9 +56438,9 @@ msgstr "" #: data/json/items/armor/bandolier.json msgid "stone pouch" msgid_plural "stone pouches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de piedras" +msgstr[1] "bolsas de piedras" +msgstr[2] "bolsas de piedras" #. ~ Description for {'str': 'stone pouch', 'str_pl': 'stone pouches'} #: data/json/items/armor/bandolier.json @@ -56213,9 +56454,9 @@ msgstr "" #: data/json/items/armor/bandolier.json msgid "large grenade pouch" msgid_plural "large grenade pouches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolso grande de granadas" +msgstr[1] "bolsos grandes de granadas" +msgstr[2] "bolsos grandes de granadas" #. ~ Use action holster_prompt for {'str': 'large grenade pouch', 'str_pl': #. 'large grenade pouches'}. @@ -56428,9 +56669,9 @@ msgstr "Es un obi gi ancho y negro." #: data/json/items/armor/belts.json msgid "police duty belt" msgid_plural "police duty belts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón de policía" +msgstr[1] "cinturones de policía" +msgstr[2] "cinturones de policía" #. ~ Use action holster_msg for {'str': 'police duty belt'}. #: data/json/items/armor/belts.json @@ -56499,9 +56740,9 @@ msgstr "" #: data/json/items/armor/belts.json msgid "webbing belt" msgid_plural "webbing belts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón cincha" +msgstr[1] "cinturones cincha" +msgstr[2] "cinturones cincha" #. ~ Description for {'str': 'webbing belt'} #: data/json/items/armor/belts.json @@ -56542,9 +56783,9 @@ msgstr "Son botas de cuero duras. Muy duraderas." #: data/json/items/armor/boots.json msgid "pair of occult boots" msgid_plural "pairs of occult boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas místicas" +msgstr[1] "pares de botas místicas" +msgstr[2] "pares de botas místicas" #. ~ Description for {'str': 'pair of occult boots', 'str_pl': 'pairs of #. occult boots'} @@ -56783,9 +57024,9 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of scrap boots" msgid_plural "pairs of scrap boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas de chatarra" +msgstr[1] "pares de botas de chatarra" +msgstr[2] "pares de botas de chatarra" #. ~ Description for {'str': 'pair of scrap boots', 'str_pl': 'pairs of scrap #. boots'} @@ -56997,9 +57238,9 @@ msgstr "Son sandalias simples. Muy difícil correr con esto puesto." #: data/json/items/armor/boots.json msgid "pair of expensive flip-flops" msgid_plural "pairs of flip-flops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de ojotas caras" +msgstr[1] "pares de ojotas caras" +msgstr[2] "pares de ojotas caras" #. ~ Description for {'str': 'pair of expensive flip-flops', 'str_pl': 'pairs #. of flip-flops'} @@ -57342,9 +57583,9 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of heelys (off)" msgid_plural "pairs of heelys (off)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de heelys (apag.)" +msgstr[1] "pares de heelys (apag.)" +msgstr[2] "pares de heelys (apag.)" #. ~ Use action msg for {'str': 'pair of heelys (off)', 'str_pl': 'pairs of #. heelys (off)'}. @@ -57362,9 +57603,9 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of heelys (on)" msgid_plural "pairs of heelys (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de heelys (enc.)" +msgstr[1] "pares de heelys (enc.)" +msgstr[2] "pares de heelys (enc.)" #. ~ Use action msg for {'str': 'pair of heelys (on)', 'str_pl': 'pairs of #. heelys (on)'}. @@ -57382,9 +57623,9 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of chainmail chausses" msgid_plural "pairs of chainmail chausses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de chausses cota de malla" +msgstr[1] "pares de chausses cota de malla" +msgstr[2] "pares de chausses cota de malla" #. ~ Description for {'str': 'pair of chainmail chausses', 'str_pl': 'pairs of #. chainmail chausses'} @@ -57443,9 +57684,9 @@ msgstr "Son calcetines. Se ponen en los pies." #: data/json/items/armor/boots.json msgid "pair of ankle socks" msgid_plural "pairs of ankle socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de soquetes" +msgstr[1] "pares de soquetes" +msgstr[2] "pares de soquetes" #. ~ Description for {'str': 'pair of ankle socks', 'str_pl': 'pairs of ankle #. socks'} @@ -57578,9 +57819,9 @@ msgstr "" #: data/json/items/armor/cloaks.json msgid "Foodperson's cape" msgid_plural "Foodperson's capes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capa Foodperson" +msgstr[1] "capas Foodperson" +msgstr[2] "capas Foodperson" #. ~ Description for {'str': "Foodperson's cape"} #: data/json/items/armor/cloaks.json @@ -58204,9 +58445,9 @@ msgstr "" #: data/json/items/armor/coats.json msgid "yukata" msgid_plural "yukatas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "yukata" +msgstr[1] "yukatas" +msgstr[2] "yukatas" #. ~ Description for {'str': 'yukata'} #: data/json/items/armor/coats.json @@ -58220,9 +58461,9 @@ msgstr "" #: data/json/items/armor/coats.json msgid "haori" msgid_plural "haoris" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "haori" +msgstr[1] "haoris" +msgstr[2] "haoris" #. ~ Description for {'str': 'haori'} #: data/json/items/armor/coats.json @@ -58281,9 +58522,9 @@ msgstr "" #: data/json/items/armor/coats.json msgid "ski jacket" msgid_plural "ski jackets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "campera de ski" +msgstr[1] "camperas de ski" +msgstr[2] "camperas de ski" #. ~ Description for {'str': 'ski jacket'} #: data/json/items/armor/coats.json @@ -58329,9 +58570,9 @@ msgstr "" #: data/json/items/armor/coats.json msgid "sleeveless faux fur duster" msgid_plural "sleeveless faux fur dusters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gabardina de piel sintética sin mangas" +msgstr[1] "gabardinas de piel sintética sin mangas" +msgstr[2] "gabardinas de piel sintética sin mangas" #. ~ Description for {'str': 'sleeveless faux fur duster'} #: data/json/items/armor/coats.json @@ -58410,9 +58651,9 @@ msgstr "" #: data/json/items/armor/coats.json msgid "sleeveless faux fur trenchcoat" msgid_plural "sleeveless faux fur trenchcoats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sobretodo de piel artificial sin mangas" +msgstr[1] "sobretodos de piel artificial sin mangas" +msgstr[2] "sobretodos de piel artificial sin mangas" #. ~ Description for {'str': 'sleeveless faux fur trenchcoat'} #: data/json/items/armor/coats.json @@ -58513,9 +58754,9 @@ msgstr "" #: data/json/items/armor/coats.json msgid "faux fur trenchcoat" msgid_plural "faux fur trenchcoats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sobretodo de piel artificial" +msgstr[1] "sobretodos de piel artificial" +msgstr[2] "sobretodos de piel artificial" #. ~ Description for {'str': 'faux fur trenchcoat'} #: data/json/items/armor/coats.json @@ -58830,9 +59071,9 @@ msgstr "" #: data/json/items/armor/eyewear.json msgid "pair of snow goggles" msgid_plural "pairs of snow goggles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de anteojos de nieve" +msgstr[1] "pares de anteojos de nieve" +msgstr[2] "pares de anteojos de nieve" #. ~ Description for {'str': 'pair of snow goggles', 'str_pl': 'pairs of snow #. goggles'} @@ -58911,9 +59152,9 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "pair of chainmail gloves" msgid_plural "pairs of chainmail gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes de cota de malla" +msgstr[1] "pares de guantes de cota de malla" +msgstr[2] "pares de guantes de cota de malla" #. ~ Description for {'str': 'pair of chainmail gloves', 'str_pl': 'pairs of #. chainmail gloves'} @@ -58963,9 +59204,9 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "pair of biosilicified chitin gauntlets" msgid_plural "pairs of biosilicified chitin gauntlets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes de quitina biosilicificada" +msgstr[1] "pares de guantes de quitina biosilicificada" +msgstr[2] "pares de guantes de quitina biosilicificada" #. ~ Description for {'str': 'pair of biosilicified chitin gauntlets', #. 'str_pl': 'pairs of biosilicified chitin gauntlets'} @@ -58981,9 +59222,9 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "fencing gauntlet" msgid_plural "fencing gauntlets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guante de esgrima" +msgstr[1] "guantes de esgrima" +msgstr[2] "guantes de esgrima" #. ~ Description for {'str': 'fencing gauntlet'} #: data/json/items/armor/gloves.json @@ -58997,9 +59238,9 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "fencing gauntlet (left)" msgid_plural "fencing gauntlets (left)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guante de esgrima (izq.)" +msgstr[1] "guantes de esgrima (izq.)" +msgstr[2] "guantes de esgrima (izq.)" #. ~ Description for {'str': 'fencing gauntlet (left)', 'str_pl': 'fencing #. gauntlets (left)'} @@ -59212,9 +59453,9 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "pair of fingerless survivor gloves" msgid_plural "pairs of fingerless survivor gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes de supervivencia sin dedos" +msgstr[1] "pares de guantes de supervivencia sin dedos" +msgstr[2] "pares de guantes de supervivencia sin dedos" #. ~ Description for {'str': 'pair of fingerless survivor gloves', 'str_pl': #. 'pairs of fingerless survivor gloves'} @@ -59652,9 +59893,9 @@ msgstr "" #: data/json/items/armor/hats.json msgid "drinking hat" msgid_plural "drinking hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gorra para bebidas" +msgstr[1] "gorras para bebidas" +msgstr[2] "gorras para bebidas" #. ~ Description for {'str': 'drinking hat'} #: data/json/items/armor/hats.json @@ -59758,9 +59999,9 @@ msgstr "Una gorra hecha con piel de animal. Extremadamente abrigada." #: data/json/items/armor/hats.json msgid "faux fur hat" msgid_plural "faux fur hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sombrero de piel artificial" +msgstr[1] "sombreros de piel artificial" +msgstr[2] "sombreros de piel artificial" #. ~ Description for {'str': 'faux fur hat'} #: data/json/items/armor/hats.json @@ -60227,9 +60468,9 @@ msgstr "" #: data/json/items/armor/helmets.json msgid "biosilicified chitin helmet" msgid_plural "biosilicified chitin helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casco de quitina biosilicificada" +msgstr[1] "cascos de quitina biosilicificada" +msgstr[2] "cascos de quitina biosilicificada" #. ~ Description for {'str': 'biosilicified chitin helmet'} #: data/json/items/armor/helmets.json @@ -60305,9 +60546,9 @@ msgstr "" #: data/json/items/armor/helmets.json msgid "large wolf skull" msgid_plural "large wolf skulls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "calavera grande de lobo" +msgstr[1] "calaveras grandes de lobo" +msgstr[2] "calaveras grandes de lobo" #. ~ Description for {'str': 'large wolf skull'} #: data/json/items/armor/helmets.json @@ -60405,9 +60646,9 @@ msgstr "" #: data/json/items/armor/helmets.json msgid "great helm" msgid_plural "great helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gran casco" +msgstr[1] "grandes cascos" +msgstr[2] "grandes cascos" #. ~ Description for {'str': 'great helm', 'str_pl': 'great helmets'} #: data/json/items/armor/helmets.json @@ -60619,9 +60860,9 @@ msgstr "" #: data/json/items/armor/holster.json msgid "bow sling" msgid_plural "bow slings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "correa para arco" +msgstr[1] "correas para arco" +msgstr[2] "correas para arco" #. ~ Description for {'str': 'bow sling'} #: data/json/items/armor/holster.json @@ -60668,9 +60909,9 @@ msgstr "" #: data/json/items/armor/holster.json msgid "deep concealment holster" msgid_plural "deep concealment holsters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "funda secreta" +msgstr[1] "fundas secretas" +msgstr[2] "fundas secretas" #. ~ Description for {'str': 'deep concealment holster'} #: data/json/items/armor/holster.json @@ -60877,9 +61118,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of beaded earrings" msgid_plural "pairs of beaded earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros con cuentas" +msgstr[1] "pares de aros con cuentas" +msgstr[2] "pares de aros con cuentas" #. ~ Description for {'str': 'pair of beaded earrings', 'str_pl': 'pairs of #. beaded earrings'} @@ -60912,9 +61153,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "friendship bracelet" msgid_plural "friendship bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de amistad" +msgstr[1] "pulseras de amistad" +msgstr[2] "pulseras de amistad" #. ~ Description for {'str': 'friendship bracelet'} #: data/json/items/armor/jewelry.json @@ -60928,9 +61169,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "bronze medal" msgid_plural "bronze medals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "medalla de bronce" +msgstr[1] "medallas de bronce" +msgstr[2] "medallas de bronce" #. ~ Description for {'str': 'bronze medal'} #: data/json/items/armor/jewelry.json @@ -60961,9 +61202,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet dental grill" msgid_plural "garnet dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de granate" +msgstr[1] "grills dentales de granate" +msgstr[2] "grills dentales de granate" #. ~ Description for {'str': 'garnet dental grill'} #: data/json/items/armor/jewelry.json @@ -60976,9 +61217,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst dental grill" msgid_plural "amethyst dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de amatista" +msgstr[1] "grills dentales de amatista" +msgstr[2] "grills dentales de amatista" #. ~ Description for {'str': 'amethyst dental grill'} #: data/json/items/armor/jewelry.json @@ -60991,9 +61232,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine dental grill" msgid_plural "aquamarine dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de aguamarina" +msgstr[1] "grills dentales de aguamarina" +msgstr[2] "grills dentales de aguamarina" #. ~ Description for {'str': 'aquamarine dental grill'} #: data/json/items/armor/jewelry.json @@ -61007,9 +61248,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald dental grill" msgid_plural "emerald dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de esmeralda" +msgstr[1] "grills dentales de esmeralda" +msgstr[2] "grills dentales de esmeralda" #. ~ Description for {'str': 'emerald dental grill'} #: data/json/items/armor/jewelry.json @@ -61022,9 +61263,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite dental grill" msgid_plural "alexandrite dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de alejandrita" +msgstr[1] "grills dentales de alejandrita" +msgstr[2] "grills dentales de alejandrita" #. ~ Description for {'str': 'alexandrite dental grill'} #: data/json/items/armor/jewelry.json @@ -61038,9 +61279,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby dental grill" msgid_plural "ruby dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de rubí" +msgstr[1] "grills dentales de rubí" +msgstr[2] "grills dentales de rubí" #. ~ Description for {'str': 'ruby dental grill'} #: data/json/items/armor/jewelry.json @@ -61053,9 +61294,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot dental grill" msgid_plural "peridot dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de peridoto" +msgstr[1] "grills dentales de peridoto" +msgstr[2] "grills dentales de peridoto" #. ~ Description for {'str': 'peridot dental grill'} #: data/json/items/armor/jewelry.json @@ -61068,9 +61309,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire dental grill" msgid_plural "sapphire dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de zafiro" +msgstr[1] "grills dentales de zafiro" +msgstr[2] "grills dentales de zafiro" #. ~ Description for {'str': 'sapphire dental grill'} #: data/json/items/armor/jewelry.json @@ -61083,9 +61324,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline dental grill" msgid_plural "tourmaline dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de turmalina" +msgstr[1] "grills dentales de turmalina" +msgstr[2] "grills dentales de turmalina" #. ~ Description for {'str': 'tourmaline dental grill'} #: data/json/items/armor/jewelry.json @@ -61099,9 +61340,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine dental grill" msgid_plural "citrine dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de citrino" +msgstr[1] "grills dentales de citrino" +msgstr[2] "grills dentales de citrino" #. ~ Description for {'str': 'citrine dental grill'} #: data/json/items/armor/jewelry.json @@ -61126,9 +61367,9 @@ msgstr "Un pasador para el pelo con muchos adornos." #: data/json/items/armor/jewelry.json msgid "blue topaz dental grill" msgid_plural "blue topaz dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grill dental de topacio azul" +msgstr[1] "grills dentales de topacio azul" +msgstr[2] "grills dentales de topacio azul" #. ~ Description for {'str': 'blue topaz dental grill'} #: data/json/items/armor/jewelry.json @@ -61142,9 +61383,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and gold ring" msgid_plural "diamond and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de oro y diamante" +msgstr[1] "anillos de oro y diamante" +msgstr[2] "anillos de oro y diamante" #. ~ Description for {'str': 'diamond and gold ring'} #: data/json/items/armor/jewelry.json @@ -61211,9 +61452,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of copper earrings" msgid_plural "pairs of copper earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de cobre" +msgstr[1] "pares de aros de cobre" +msgstr[2] "pares de aros de cobre" #. ~ Description for {'str': 'pair of copper earrings', 'str_pl': 'pairs of #. copper earrings'} @@ -61228,9 +61469,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "copper hairpin" msgid_plural "copper hairpins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hebilla de cobre" +msgstr[1] "hebillas de cobre" +msgstr[2] "hebillas de cobre" #. ~ Description for {'str': 'copper hairpin'} #: data/json/items/armor/jewelry.json @@ -61244,9 +61485,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "copper locket" msgid_plural "copper lockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "relicario de cobre" +msgstr[1] "relicarios de cobre" +msgstr[2] "relicarios de cobre" #. ~ Description for {'str': 'copper locket'} #: data/json/items/armor/jewelry.json @@ -61278,9 +61519,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "copper ring" msgid_plural "copper rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de cobre" +msgstr[1] "anillos de cobre" +msgstr[2] "anillos de cobre" #. ~ Description for {'str': 'copper ring'} #: data/json/items/armor/jewelry.json @@ -61294,9 +61535,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of cufflinks" msgid_plural "pairs of cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de gemelos" +msgstr[1] "pares de gemelos" +msgstr[2] "pares de gemelos" #. ~ Description for {'str': 'pair of cufflinks', 'str_pl': 'pairs of #. cufflinks'} @@ -61313,9 +61554,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of intricate cufflinks" msgid_plural "pairs of intricate cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de gemelos intrincados" +msgstr[1] "pares de gemelos intrincados" +msgstr[2] "pares de gemelos intrincados" #. ~ Description for {'str': 'pair of intricate cufflinks', 'str_pl': 'pairs #. of intricate cufflinks'} @@ -61332,9 +61573,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and gold cufflinks" msgid_plural "garnet and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de granate y oro" +msgstr[1] "pares de gemelos de granate y oro" +msgstr[2] "pares de gemelos de granate y oro" #. ~ Description for {'str_sp': 'garnet and gold cufflinks'} #. ~ Description for {'str_sp': 'garnet and silver cufflinks'} @@ -61346,9 +61587,9 @@ msgstr "Es un par de gemelos con granates incrustados." #: data/json/items/armor/jewelry.json msgid "diamond and gold cufflinks" msgid_plural "diamond and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de diamante y oro" +msgstr[1] "pares de gemelos de diamante y oro" +msgstr[2] "pares de gemelos de diamante y oro" #. ~ Description for {'str_sp': 'diamond and gold cufflinks'} #. ~ Description for {'str_sp': 'diamond and silver cufflinks'} @@ -61360,9 +61601,9 @@ msgstr "Es un par de gemelos con diamantes incrustados." #: data/json/items/armor/jewelry.json msgid "amethyst and gold cufflinks" msgid_plural "amethyst and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de amatista y oro" +msgstr[1] "pares de gemelos de amatista y oro" +msgstr[2] "pares de gemelos de amatista y oro" #. ~ Description for {'str_sp': 'amethyst and gold cufflinks'} #. ~ Description for {'str_sp': 'amethyst and silver cufflinks'} @@ -61374,9 +61615,9 @@ msgstr "Es un par de gemelos con amatistas incrustadas." #: data/json/items/armor/jewelry.json msgid "aquamarine and gold cufflinks" msgid_plural "aquamarine and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de aguamarina y oro" +msgstr[1] "pares de gemelos de aguamarina y oro" +msgstr[2] "pares de gemelos de aguamarina y oro" #. ~ Description for {'str_sp': 'aquamarine and gold cufflinks'} #. ~ Description for {'str_sp': 'aquamarine and silver cufflinks'} @@ -61388,9 +61629,9 @@ msgstr "Es un par de gemelos con aguamarinas incrustadas." #: data/json/items/armor/jewelry.json msgid "emerald and gold cufflinks" msgid_plural "emerald and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de esmeralda y oro" +msgstr[1] "pares de gemelos de esmeralda y oro" +msgstr[2] "pares de gemelos de esmeralda y oro" #. ~ Description for {'str_sp': 'emerald and gold cufflinks'} #. ~ Description for {'str_sp': 'emerald and silver cufflinks'} @@ -61402,9 +61643,9 @@ msgstr "Es un par de gemelos con esmeraldas incrustadas." #: data/json/items/armor/jewelry.json msgid "alexandrite and gold cufflinks" msgid_plural "alexandrite and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de alejandrita y oro" +msgstr[1] "pares de gemelos de alejandrita y oro" +msgstr[2] "pares de gemelos de alejandrita y oro" #. ~ Description for {'str_sp': 'alexandrite and gold cufflinks'} #. ~ Description for {'str_sp': 'alexandrite and silver cufflinks'} @@ -61416,9 +61657,9 @@ msgstr "Es un par de gemelos con alejandritas incrustadas." #: data/json/items/armor/jewelry.json msgid "ruby and gold cufflinks" msgid_plural "ruby and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de rubí y oro" +msgstr[1] "pares de gemelos de rubí y oro" +msgstr[2] "pares de gemelos de rubí y oro" #. ~ Description for {'str_sp': 'ruby and gold cufflinks'} #. ~ Description for {'str_sp': 'ruby and silver cufflinks'} @@ -61430,9 +61671,9 @@ msgstr "Es un par de gemelos con rubíes incrustados." #: data/json/items/armor/jewelry.json msgid "peridot and gold cufflinks" msgid_plural "peridot and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de peridoto y oro" +msgstr[1] "pares de gemelos de peridoto y oro" +msgstr[2] "pares de gemelos de peridoto y oro" #. ~ Description for {'str_sp': 'peridot and gold cufflinks'} #. ~ Description for {'str_sp': 'peridot and silver cufflinks'} @@ -61444,9 +61685,9 @@ msgstr "Es un par de gemelos con peridotos incrustados." #: data/json/items/armor/jewelry.json msgid "sapphire and gold cufflinks" msgid_plural "sapphire and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de zafiro y oro" +msgstr[1] "pares de gemelos de zafiro y oro" +msgstr[2] "pares de gemelos de zafiro y oro" #. ~ Description for {'str_sp': 'sapphire and gold cufflinks'} #. ~ Description for {'str_sp': 'sapphire and silver cufflinks'} @@ -61458,9 +61699,9 @@ msgstr "Es un par de gemelos con zafiros incrustados." #: data/json/items/armor/jewelry.json msgid "tourmaline and gold cufflinks" msgid_plural "tourmaline and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de turmalina y oro" +msgstr[1] "pares de gemelos de turmalina y oro" +msgstr[2] "pares de gemelos de turmalina y oro" #. ~ Description for {'str_sp': 'tourmaline and gold cufflinks'} #. ~ Description for {'str_sp': 'tourmaline and silver cufflinks'} @@ -61472,9 +61713,9 @@ msgstr "Es un par de gemelos con turmalinas incrustadas." #: data/json/items/armor/jewelry.json msgid "citrine and gold cufflinks" msgid_plural "citrine and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de citrino y oro" +msgstr[1] "pares de gemelos de citrino y oro" +msgstr[2] "pares de gemelos de citrino y oro" #. ~ Description for {'str_sp': 'citrine and gold cufflinks'} #. ~ Description for {'str_sp': 'citrine and silver cufflinks'} @@ -61486,9 +61727,9 @@ msgstr "Es un par de gemelos con citrinos incrustados." #: data/json/items/armor/jewelry.json msgid "blue topaz and gold cufflinks" msgid_plural "blue topaz and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de topacio azul y oro" +msgstr[1] "pares de gemelos de topacio azul y oro" +msgstr[2] "pares de gemelos de topacio azul y oro" #. ~ Description for {'str_sp': 'blue topaz and gold cufflinks'} #. ~ Description for {'str_sp': 'blue topaz and silver cufflinks'} @@ -61500,9 +61741,9 @@ msgstr "Es un par de gemelos con topacios azules incrustados." #: data/json/items/armor/jewelry.json msgid "opal and gold cufflinks" msgid_plural "opal and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de ópalo y oro" +msgstr[1] "pares de gemelos de ópalo y oro" +msgstr[2] "pares de gemelos de ópalo y oro" #. ~ Description for {'str_sp': 'opal and gold cufflinks'} #. ~ Description for {'str_sp': 'opal and silver cufflinks'} @@ -61514,9 +61755,9 @@ msgstr "Es un par de gemelos con ópalos incrustados." #: data/json/items/armor/jewelry.json msgid "pearl and gold cufflinks" msgid_plural "pearl and gold cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de perla y oro" +msgstr[1] "pares de gemelos de perla y oro" +msgstr[2] "pares de gemelos de perla y oro" #. ~ Description for {'str_sp': 'pearl and gold cufflinks'} #. ~ Description for {'str_sp': 'pearl and silver cufflinks'} @@ -61528,198 +61769,198 @@ msgstr "Es un par de gemelos con perlas incrustadas." #: data/json/items/armor/jewelry.json msgid "garnet and silver cufflinks" msgid_plural "garnet and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de granate y plata" +msgstr[1] "pares de gemelos de granate y plata" +msgstr[2] "pares de gemelos de granate y plata" #: data/json/items/armor/jewelry.json msgid "diamond and silver cufflinks" msgid_plural "diamond and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de diamante y plata" +msgstr[1] "pares de gemelos de diamante y plata" +msgstr[2] "pares de gemelos de diamante y plata" #: data/json/items/armor/jewelry.json msgid "amethyst and silver cufflinks" msgid_plural "amethyst and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de amatista y plata" +msgstr[1] "pares de gemelos de amatista y plata" +msgstr[2] "pares de gemelos de amatista y plata" #: data/json/items/armor/jewelry.json msgid "aquamarine and silver cufflinks" msgid_plural "aquamarine and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de aguamarina y plata" +msgstr[1] "pares de gemelos de aguamarina y plata" +msgstr[2] "pares de gemelos de aguamarina y plata" #: data/json/items/armor/jewelry.json msgid "emerald and silver cufflinks" msgid_plural "emerald and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de esmeralda y plata" +msgstr[1] "pares de gemelos de esmeralda y plata" +msgstr[2] "pares de gemelos de esmeralda y plata" #: data/json/items/armor/jewelry.json msgid "alexandrite and silver cufflinks" msgid_plural "alexandrite and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de alejandrita y plata" +msgstr[1] "pares de gemelos de alejandrita y plata" +msgstr[2] "pares de gemelos de alejandrita y plata" #: data/json/items/armor/jewelry.json msgid "ruby and silver cufflinks" msgid_plural "ruby and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de rubí y plata" +msgstr[1] "pares de gemelos de rubí y plata" +msgstr[2] "pares de gemelos de rubí y plata" #: data/json/items/armor/jewelry.json msgid "peridot and silver cufflinks" msgid_plural "peridot and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de peridoto y plata" +msgstr[1] "pares de gemelos de peridoto y plata" +msgstr[2] "pares de gemelos de peridoto y plata" #: data/json/items/armor/jewelry.json msgid "sapphire and silver cufflinks" msgid_plural "sapphire and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de zafiro y plata" +msgstr[1] "pares de gemelos de zafiro y plata" +msgstr[2] "pares de gemelos de zafiro y plata" #: data/json/items/armor/jewelry.json msgid "tourmaline and silver cufflinks" msgid_plural "tourmaline and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de turmalina y plata" +msgstr[1] "pares de gemelos de turmalina y plata" +msgstr[2] "pares de gemelos de turmalina y plata" #: data/json/items/armor/jewelry.json msgid "citrine and silver cufflinks" msgid_plural "citrine and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de citrino y plata" +msgstr[1] "pares de gemelos de citrino y plata" +msgstr[2] "pares de gemelos de citrino y plata" #: data/json/items/armor/jewelry.json msgid "blue topaz and silver cufflinks" msgid_plural "blue topaz and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de topacio azul y plata" +msgstr[1] "pares de gemelos de topacio azul y plata" +msgstr[2] "pares de gemelos de topacio azul y plata" #: data/json/items/armor/jewelry.json msgid "opal and silver cufflinks" msgid_plural "opal and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de ópalo y plata" +msgstr[1] "pares de gemelos de ópalo y plata" +msgstr[2] "pares de gemelos de ópalo y plata" #: data/json/items/armor/jewelry.json msgid "pearl and silver cufflinks" msgid_plural "pearl and silver cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de perla y plata" +msgstr[1] "pares de gemelos de perla y plata" +msgstr[2] "pares de gemelos de perla y plata" #: data/json/items/armor/jewelry.json msgid "garnet and platinum cufflinks" msgid_plural "garnet and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de granate y platino" +msgstr[1] "pares de gemelos de granate y platino" +msgstr[2] "pares de gemelos de granate y platino" #: data/json/items/armor/jewelry.json msgid "diamond and platinum cufflinks" msgid_plural "diamond and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de diamante y platino" +msgstr[1] "pares de gemelos de diamante y platino" +msgstr[2] "pares de gemelos de diamante y platino" #: data/json/items/armor/jewelry.json msgid "amethyst and platinum cufflinks" msgid_plural "amethyst and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de amatista y platino" +msgstr[1] "pares de gemelos de amatista y platino" +msgstr[2] "pares de gemelos de amatista y platino" #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum cufflinks" msgid_plural "aquamarine and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de aguamarina y platino" +msgstr[1] "pares de gemelos de aguamarina y platino" +msgstr[2] "pares de gemelos de aguamarina y platino" #: data/json/items/armor/jewelry.json msgid "emerald and platinum cufflinks" msgid_plural "emerald and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de esmeralda y platino" +msgstr[1] "pares de gemelos de esmeralda y platino" +msgstr[2] "pares de gemelos de esmeralda y platino" #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum cufflinks" msgid_plural "alexandrite and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de alejandrita y platino" +msgstr[1] "pares de gemelos de alejandrita y platino" +msgstr[2] "pares de gemelos de alejandrita y platino" #: data/json/items/armor/jewelry.json msgid "ruby and platinum cufflinks" msgid_plural "ruby and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de rubí y platino" +msgstr[1] "pares de gemelos de rubí y platino" +msgstr[2] "pares de gemelos de rubí y platino" #: data/json/items/armor/jewelry.json msgid "peridot and platinum cufflinks" msgid_plural "peridot and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de peridoto y platino" +msgstr[1] "pares de gemelos de peridoto y platino" +msgstr[2] "pares de gemelos de peridoto y platino" #: data/json/items/armor/jewelry.json msgid "sapphire and platinum cufflinks" msgid_plural "sapphire and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de zafiro y platino" +msgstr[1] "pares de gemelos de zafiro y platino" +msgstr[2] "pares de gemelos de zafiro y platino" #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum cufflinks" msgid_plural "tourmaline and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de turmalina y platino" +msgstr[1] "pares de gemelos de turmalina y platino" +msgstr[2] "pares de gemelos de turmalina y platino" #: data/json/items/armor/jewelry.json msgid "citrine and platinum cufflinks" msgid_plural "citrine and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de citrino y platino" +msgstr[1] "pares de gemelos de citrino y platino" +msgstr[2] "pares de gemelos de citrino y platino" #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum cufflinks" msgid_plural "blue topaz and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de topacio azul y platino" +msgstr[1] "pares de gemelos de topacio azul y platino" +msgstr[2] "pares de gemelos de topacio azul y platino" #: data/json/items/armor/jewelry.json msgid "opal and platinum cufflinks" msgid_plural "opal and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de ópalo y platino" +msgstr[1] "pares de gemelos de ópalo y platino" +msgstr[2] "pares de gemelos de ópalo y platino" #: data/json/items/armor/jewelry.json msgid "pearl and platinum cufflinks" msgid_plural "pearl and platinum cufflinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pares de gemelos de perla y platino" +msgstr[1] "pares de gemelos de perla y platino" +msgstr[2] "pares de gemelos de perla y platino" #: data/json/items/armor/jewelry.json msgid "plug" @@ -61773,9 +62014,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of gold earrings" msgid_plural "pairs of gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de oro" +msgstr[1] "pares de aros de oro" +msgstr[2] "pares de aros de oro" #. ~ Description for {'str': 'pair of gold earrings', 'str_pl': 'pairs of gold #. earrings'} @@ -61790,9 +62031,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "gold hairpin" msgid_plural "gold hairpins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hebilla de oro" +msgstr[1] "hebillas de oro" +msgstr[2] "hebillas de oro" #. ~ Description for {'str': 'gold hairpin'} #: data/json/items/armor/jewelry.json @@ -61806,9 +62047,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "gold locket" msgid_plural "gold lockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "relicario de oro" +msgstr[1] "relicarios de oro" +msgstr[2] "relicarios de oro" #. ~ Description for {'str': 'gold locket'} #: data/json/items/armor/jewelry.json @@ -61824,9 +62065,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "gold medal" msgid_plural "gold medals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "medalla de oro" +msgstr[1] "medallas de oro" +msgstr[2] "medallas de oro" #. ~ Description for {'str': 'gold medal'} #: data/json/items/armor/jewelry.json @@ -61842,9 +62083,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "gold necklace" msgid_plural "gold necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "collar de oro" +msgstr[1] "collares de oro" +msgstr[2] "collares de oro" #. ~ Description for {'str': 'gold necklace'} #: data/json/items/armor/jewelry.json @@ -61906,9 +62147,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "silver watch" msgid_plural "silver watches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "reloj de plata" +msgstr[1] "relojes de plata" +msgstr[2] "relojes de plata" #. ~ Description for {'str': 'silver watch', 'str_pl': 'silver watches'} #: data/json/items/armor/jewelry.json @@ -61940,9 +62181,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of silver earrings" msgid_plural "pairs of silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de plata" +msgstr[1] "pares de aros de plata" +msgstr[2] "pares de aros de plata" #. ~ Description for {'str': 'pair of silver earrings', 'str_pl': 'pairs of #. silver earrings'} @@ -62050,9 +62291,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "platinum watch" msgid_plural "platinum watches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "reloj de platino" +msgstr[1] "relojes de platino" +msgstr[2] "relojes de platino" #. ~ Description for {'str': 'platinum watch', 'str_pl': 'platinum watches'} #: data/json/items/armor/jewelry.json @@ -62066,9 +62307,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "platinum bracelet" msgid_plural "platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de platino" +msgstr[1] "pulseras de platino" +msgstr[2] "pulseras de platino" #. ~ Description for {'str': 'platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -62082,9 +62323,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "platinum dental grill" msgid_plural "platinum dental grills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grills dentales de platino" +msgstr[1] "grills dentales de platino" +msgstr[2] "grills dentales de platino" #. ~ Description for {'str': 'platinum dental grill'} #: data/json/items/armor/jewelry.json @@ -62099,9 +62340,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of platinum earrings" msgid_plural "pairs of platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de platino" +msgstr[1] "pares de aros de platino" +msgstr[2] "pares de aros de platino" #. ~ Description for {'str': 'pair of platinum earrings', 'str_pl': 'pairs of #. platinum earrings'} @@ -62118,9 +62359,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "platinum hairpin" msgid_plural "platinum hairpins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hebilla de platino" +msgstr[1] "hebillas de platino" +msgstr[2] "hebillas de platino" #. ~ Description for {'str': 'platinum hairpin'} #: data/json/items/armor/jewelry.json @@ -62136,9 +62377,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "platinum locket" msgid_plural "platinum lockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "relicario de platino" +msgstr[1] "relicarios de platino" +msgstr[2] "relicarios de platino" #. ~ Description for {'str': 'platinum locket'} #: data/json/items/armor/jewelry.json @@ -62152,9 +62393,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "platinum necklace" msgid_plural "platinum necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "collar de platino" +msgstr[1] "collares de platino" +msgstr[2] "collares de platino" #. ~ Description for {'str': 'platinum necklace'} #: data/json/items/armor/jewelry.json @@ -62168,9 +62409,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "platinum ring" msgid_plural "platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de platino" +msgstr[1] "anillos de platino" +msgstr[2] "anillos de platino" #. ~ Description for {'str': 'platinum ring'} #: data/json/items/armor/jewelry.json @@ -62184,9 +62425,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "engagement ring" msgid_plural "engagement rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de compromiso" +msgstr[1] "anillos de compromiso" +msgstr[2] "anillos de compromiso" #. ~ Description for {'str': 'engagement ring'} #: data/json/items/armor/jewelry.json @@ -62202,9 +62443,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "purity ring" msgid_plural "purity rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillos de castidad" +msgstr[1] "anillos de castidad" +msgstr[2] "anillos de castidad" #. ~ Description for {'str': 'purity ring'} #: data/json/items/armor/jewelry.json @@ -62219,9 +62460,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "signet ring" msgid_plural "signet rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de sello" +msgstr[1] "anillos de sello" +msgstr[2] "anillos de sello" #. ~ Description for {'str': 'signet ring'} #: data/json/items/armor/jewelry.json @@ -62237,9 +62478,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "wedding ring" msgid_plural "wedding rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de casamiento" +msgstr[1] "anillos de casamiento" +msgstr[2] "anillos de casamiento" #. ~ Description for {'str': 'wedding ring'} #: data/json/items/armor/jewelry.json @@ -62269,9 +62510,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "silver hairpin" msgid_plural "silver hairpins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hebilla de plata" +msgstr[1] "hebillas de plata" +msgstr[2] "hebillas de plata" #. ~ Description for {'str': 'silver hairpin'} #: data/json/items/armor/jewelry.json @@ -62285,9 +62526,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "silver locket" msgid_plural "silver lockets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "relicario de plata" +msgstr[1] "relicarios de plata" +msgstr[2] "relicarios de plata" #. ~ Description for {'str': 'silver locket'} #: data/json/items/armor/jewelry.json @@ -62302,9 +62543,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "silver medal" msgid_plural "silver medals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "medalla de plata" +msgstr[1] "medallas de plata" +msgstr[2] "medallas de plata" #. ~ Description for {'str': 'silver medal'} #: data/json/items/armor/jewelry.json @@ -62474,9 +62715,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "doctor badge" msgid_plural "doctor badges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "placa de médico" +msgstr[1] "placas de médico" +msgstr[2] "placas de médico" #. ~ Description for {'str': 'doctor badge'} #: data/json/items/armor/jewelry.json @@ -62637,9 +62878,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of diamond and gold earrings" msgid_plural "pairs of diamond and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de diamante y oro" +msgstr[1] "pares de aros de diamante y oro" +msgstr[2] "pares de aros de diamante y oro" #. ~ Description for {'str': 'pair of diamond and gold earrings', 'str_pl': #. 'pairs of diamond and gold earrings'} @@ -62654,9 +62895,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of garnet and gold earrings" msgid_plural "pairs of garnet and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de granate y oro" +msgstr[1] "pares de aros de granate y oro" +msgstr[2] "pares de aros de granate y oro" #. ~ Description for {'str': 'pair of garnet and gold earrings', 'str_pl': #. 'pairs of garnet and gold earrings'} @@ -62671,9 +62912,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of amethyst and gold earrings" msgid_plural "pairs of amethyst and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de amatista y oro" +msgstr[1] "pares de aros de amatista y oro" +msgstr[2] "pares de aros de amatista y oro" #. ~ Description for {'str': 'pair of amethyst and gold earrings', 'str_pl': #. 'pairs of amethyst and gold earrings'} @@ -62688,9 +62929,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of aquamarine and gold earrings" msgid_plural "pairs of aquamarine and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de aguamarina y oro" +msgstr[1] "pares de aros de aguamarina y oro" +msgstr[2] "pares de aros de aguamarina y oro" #. ~ Description for {'str': 'pair of aquamarine and gold earrings', 'str_pl': #. 'pairs of aquamarine and gold earrings'} @@ -62705,9 +62946,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of emerald and gold earrings" msgid_plural "pairs of emerald and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de esmeralda y oro" +msgstr[1] "pares de aros de esmeralda y oro" +msgstr[2] "pares de aros de esmeralda y oro" #. ~ Description for {'str': 'pair of emerald and gold earrings', 'str_pl': #. 'pairs of emerald and gold earrings'} @@ -62722,9 +62963,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of alexandrite and gold earrings" msgid_plural "pairs of alexandrite and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de alejandrita y oro" +msgstr[1] "pares de aros de alejandrita y oro" +msgstr[2] "pares de aros de alejandrita y oro" #. ~ Description for {'str': 'pair of alexandrite and gold earrings', #. 'str_pl': 'pairs of alexandrite and gold earrings'} @@ -62739,9 +62980,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of ruby and gold earrings" msgid_plural "pairs of ruby and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de rubí y oro" +msgstr[1] "pares de aros de rubí y oro" +msgstr[2] "pares de aros de rubí y oro" #. ~ Description for {'str': 'pair of ruby and gold earrings', 'str_pl': #. 'pairs of ruby and gold earrings'} @@ -62756,9 +62997,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of peridot and gold earrings" msgid_plural "pairs of peridot and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de peridoto y oro" +msgstr[1] "pares de aros de peridoto y oro" +msgstr[2] "pares de aros de peridoto y oro" #. ~ Description for {'str': 'pair of peridot and gold earrings', 'str_pl': #. 'pairs of peridot and gold earrings'} @@ -62773,9 +63014,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of sapphire and gold earrings" msgid_plural "pairs of sapphire and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de zafiro y oro" +msgstr[1] "pares de aros de zafiro y oro" +msgstr[2] "pares de aros de zafiro y oro" #. ~ Description for {'str': 'pair of sapphire and gold earrings', 'str_pl': #. 'pairs of sapphire and gold earrings'} @@ -62790,9 +63031,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of tourmaline and gold earrings" msgid_plural "pairs of tourmaline and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de turmalina y oro" +msgstr[1] "pares de aros de turmalina y oro" +msgstr[2] "pares de aros de turmalina y oro" #. ~ Description for {'str': 'pair of tourmaline and gold earrings', 'str_pl': #. 'pairs of tourmaline and gold earrings'} @@ -62807,9 +63048,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of citrine and gold earrings" msgid_plural "pairs of citrine and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de citrino y oro" +msgstr[1] "pares de aros de citrino y oro" +msgstr[2] "pares de aros de citrino y oro" #. ~ Description for {'str': 'pair of citrine and gold earrings', 'str_pl': #. 'pairs of citrine and gold earrings'} @@ -62824,9 +63065,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of blue topaz and gold earrings" msgid_plural "pairs of blue topaz and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de topacio azul y oro" +msgstr[1] "pares de aros de topacio azul y oro" +msgstr[2] "pares de aros de topacio azul y oro" #. ~ Description for {'str': 'pair of blue topaz and gold earrings', 'str_pl': #. 'pairs of blue topaz and gold earrings'} @@ -62841,9 +63082,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of opal and gold earrings" msgid_plural "pairs of opal and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de ópalo y oro" +msgstr[1] "pares de aros de ópalo y oro" +msgstr[2] "pares de aros de ópalo y oro" #. ~ Description for {'str': 'pair of opal and gold earrings', 'str_pl': #. 'pairs of opal and gold earrings'} @@ -62858,9 +63099,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of pearl and gold earrings" msgid_plural "pairs of pearl and gold earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de perla y oro" +msgstr[1] "pares de aros de perla y oro" +msgstr[2] "pares de aros de perla y oro" #. ~ Description for {'str': 'pair of pearl and gold earrings', 'str_pl': #. 'pairs of pearl and gold earrings'} @@ -62875,9 +63116,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of diamond and silver earrings" msgid_plural "pairs of diamond and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de diamante y plata" +msgstr[1] "pares de aros de diamante y plata" +msgstr[2] "pares de aros de diamante y plata" #. ~ Description for {'str': 'pair of diamond and silver earrings', 'str_pl': #. 'pairs of diamond and silver earrings'} @@ -62892,9 +63133,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of garnet and silver earrings" msgid_plural "pairs of garnet and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de granate y plata" +msgstr[1] "pares de aros de granate y plata" +msgstr[2] "pares de aros de granate y plata" #. ~ Description for {'str': 'pair of garnet and silver earrings', 'str_pl': #. 'pairs of garnet and silver earrings'} @@ -62926,9 +63167,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of aquamarine and silver earrings" msgid_plural "pairs of aquamarine and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de aguamarina y plata" +msgstr[1] "pares de aros de aguamarina y plata" +msgstr[2] "pares de aros de aguamarina y plata" #. ~ Description for {'str': 'pair of aquamarine and silver earrings', #. 'str_pl': 'pairs of aquamarine and silver earrings'} @@ -62943,9 +63184,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of emerald and silver earrings" msgid_plural "pairs of emerald and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de esmeralda y plata" +msgstr[1] "pares de aros de esmeralda y plata" +msgstr[2] "pares de aros de esmeralda y plata" #. ~ Description for {'str': 'pair of emerald and silver earrings', 'str_pl': #. 'pairs of emerald and silver earrings'} @@ -62960,9 +63201,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of alexandrite and silver earrings" msgid_plural "pairs of alexandrite and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de alejandrita y plata" +msgstr[1] "pares de aros de alejandrita y plata" +msgstr[2] "pares de aros de alejandrita y plata" #. ~ Description for {'str': 'pair of alexandrite and silver earrings', #. 'str_pl': 'pairs of alexandrite and silver earrings'} @@ -62977,9 +63218,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of ruby and silver earrings" msgid_plural "pairs of ruby and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de rubí y plata" +msgstr[1] "pares de aros de rubí y plata" +msgstr[2] "pares de aros de rubí y plata" #. ~ Description for {'str': 'pair of ruby and silver earrings', 'str_pl': #. 'pairs of ruby and silver earrings'} @@ -62994,9 +63235,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of peridot and silver earrings" msgid_plural "pairs of peridot and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de peridoto y plata" +msgstr[1] "pares de aros de peridoto y plata" +msgstr[2] "pares de aros de peridoto y plata" #. ~ Description for {'str': 'pair of peridot and silver earrings', 'str_pl': #. 'pairs of peridot and silver earrings'} @@ -63011,9 +63252,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of sapphire and silver earrings" msgid_plural "pairs of sapphire and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de zafiro y plata" +msgstr[1] "pares de aros de zafiro y plata" +msgstr[2] "pares de aros de zafiro y plata" #. ~ Description for {'str': 'pair of sapphire and silver earrings', 'str_pl': #. 'pairs of sapphire and silver earrings'} @@ -63028,9 +63269,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of tourmaline and silver earrings" msgid_plural "pairs of tourmaline and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de turmalina y plata" +msgstr[1] "pares de aros de turmalina y plata" +msgstr[2] "pares de aros de turmalina y plata" #. ~ Description for {'str': 'pair of tourmaline and silver earrings', #. 'str_pl': 'pairs of tourmaline and silver earrings'} @@ -63045,9 +63286,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of citrine and silver earrings" msgid_plural "pairs of citrine and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de citrino y plata" +msgstr[1] "pares de aros de citrino y plata" +msgstr[2] "pares de aros de citrino y plata" #. ~ Description for {'str': 'pair of citrine and silver earrings', 'str_pl': #. 'pairs of citrine and silver earrings'} @@ -63062,9 +63303,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of blue topaz and silver earrings" msgid_plural "pairs of blue topaz and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de topacio azul y plata" +msgstr[1] "pares de aros de topacio azul y plata" +msgstr[2] "pares de aros de topacio azul y plata" #. ~ Description for {'str': 'pair of blue topaz and silver earrings', #. 'str_pl': 'pairs of blue topaz and silver earrings'} @@ -63079,9 +63320,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of opal and silver earrings" msgid_plural "pairs of opal and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de ópalo y plata" +msgstr[1] "pares de aros de ópalo y plata" +msgstr[2] "pares de aros de ópalo y plata" #. ~ Description for {'str': 'pair of opal and silver earrings', 'str_pl': #. 'pairs of opal and silver earrings'} @@ -63096,9 +63337,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of pearl and silver earrings" msgid_plural "pairs of pearl and silver earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de perla y plata" +msgstr[1] "pares de aros de perla y plata" +msgstr[2] "pares de aros de perla y plata" #. ~ Description for {'str': 'pair of pearl and silver earrings', 'str_pl': #. 'pairs of pearl and silver earrings'} @@ -63113,9 +63354,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of diamond and platinum earrings" msgid_plural "pairs of diamond and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de diamante y platino" +msgstr[1] "pares de aros de diamante y platino" +msgstr[2] "pares de aros de diamante y platino" #. ~ Description for {'str': 'pair of diamond and platinum earrings', #. 'str_pl': 'pairs of diamond and platinum earrings'} @@ -63130,9 +63371,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of garnet and platinum earrings" msgid_plural "pairs of garnet and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de granate y platino" +msgstr[1] "pares de aros de granate y platino" +msgstr[2] "pares de aros de granate y platino" #. ~ Description for {'str': 'pair of garnet and platinum earrings', 'str_pl': #. 'pairs of garnet and platinum earrings'} @@ -63147,9 +63388,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of amethyst and platinum earrings" msgid_plural "pairs of amethyst and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de amatista y platino" +msgstr[1] "pares de aros de amatista y platino" +msgstr[2] "pares de aros de amatista y platino" #. ~ Description for {'str': 'pair of amethyst and platinum earrings', #. 'str_pl': 'pairs of amethyst and platinum earrings'} @@ -63164,9 +63405,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of aquamarine and platinum earrings" msgid_plural "pairs of aquamarine and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de aguamarina y platino" +msgstr[1] "pares de aros de aguamarina y platino" +msgstr[2] "pares de aros de aguamarina y platino" #. ~ Description for {'str': 'pair of aquamarine and platinum earrings', #. 'str_pl': 'pairs of aquamarine and platinum earrings'} @@ -63181,9 +63422,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of emerald and platinum earrings" msgid_plural "pairs of emerald and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de esmeralda y platino" +msgstr[1] "pares de aros de esmeralda y platino" +msgstr[2] "pares de aros de esmeralda y platino" #. ~ Description for {'str': 'pair of emerald and platinum earrings', #. 'str_pl': 'pairs of emerald and platinum earrings'} @@ -63198,9 +63439,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of alexandrite and platinum earrings" msgid_plural "pairs of alexandrite and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de alejandrita y platino" +msgstr[1] "pares de aros de alejandrita y platino" +msgstr[2] "pares de aros de alejandrita y platino" #. ~ Description for {'str': 'pair of alexandrite and platinum earrings', #. 'str_pl': 'pairs of alexandrite and platinum earrings'} @@ -63215,9 +63456,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of ruby and platinum earrings" msgid_plural "pairs of ruby and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de rubí y platino" +msgstr[1] "pares de aros de rubí y platino" +msgstr[2] "pares de aros de rubí y platino" #. ~ Description for {'str': 'pair of ruby and platinum earrings', 'str_pl': #. 'pairs of ruby and platinum earrings'} @@ -63232,9 +63473,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of peridot and platinum earrings" msgid_plural "pairs of peridot and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de peridoto y platino" +msgstr[1] "pares de aros de peridoto y platino" +msgstr[2] "pares de aros de peridoto y platino" #. ~ Description for {'str': 'pair of peridot and platinum earrings', #. 'str_pl': 'pairs of peridot and platinum earrings'} @@ -63249,9 +63490,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of sapphire and platinum earrings" msgid_plural "pairs of sapphire and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de zafiro y platino" +msgstr[1] "pares de aros de zafiro y platino" +msgstr[2] "pares de aros de zafiro y platino" #. ~ Description for {'str': 'pair of sapphire and platinum earrings', #. 'str_pl': 'pairs of sapphire and platinum earrings'} @@ -63266,9 +63507,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of tourmaline and platinum earrings" msgid_plural "pairs of tourmaline and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de turmalina y platino" +msgstr[1] "pares de aros de turmalina y platino" +msgstr[2] "pares de aros de turmalina y platino" #. ~ Description for {'str': 'pair of tourmaline and platinum earrings', #. 'str_pl': 'pairs of tourmaline and platinum earrings'} @@ -63283,9 +63524,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of citrine and platinum earrings" msgid_plural "pairs of citrine and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de citrino y platino" +msgstr[1] "pares de aros de citrino y platino" +msgstr[2] "pares de aros de citrino y platino" #. ~ Description for {'str': 'pair of citrine and platinum earrings', #. 'str_pl': 'pairs of citrine and platinum earrings'} @@ -63300,9 +63541,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of blue topaz and platinum earrings" msgid_plural "pairs of blue topaz and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de topacio azul y platino" +msgstr[1] "pares de aros de topacio azul y platino" +msgstr[2] "pares de aros de topacio azul y platino" #. ~ Description for {'str': 'pair of blue topaz and platinum earrings', #. 'str_pl': 'pairs of blue topaz and platinum earrings'} @@ -63317,9 +63558,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of opal and platinum earrings" msgid_plural "pairs of opal and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de ópalo y platino" +msgstr[1] "pares de aros de ópalo y platino" +msgstr[2] "pares de aros de ópalo y platino" #. ~ Description for {'str': 'pair of opal and platinum earrings', 'str_pl': #. 'pairs of opal and platinum earrings'} @@ -63334,9 +63575,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of pearl and platinum earrings" msgid_plural "pairs of pearl and platinum earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de aros de perla y platino" +msgstr[1] "pares de aros de perla y platino" +msgstr[2] "pares de aros de perla y platino" #. ~ Description for {'str': 'pair of pearl and platinum earrings', 'str_pl': #. 'pairs of pearl and platinum earrings'} @@ -63351,9 +63592,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and gold ring" msgid_plural "garnet and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de granate y oro" +msgstr[1] "anillos de granate y oro" +msgstr[2] "anillos de granate y oro" #. ~ Description for {'str': 'garnet and gold ring'} #: data/json/items/armor/jewelry.json @@ -63367,9 +63608,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and gold ring" msgid_plural "amethyst and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de amatista y oro" +msgstr[1] "anillos de amatista y oro" +msgstr[2] "anillos de amatista y oro" #. ~ Description for {'str': 'amethyst and gold ring'} #: data/json/items/armor/jewelry.json @@ -63383,9 +63624,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and gold ring" msgid_plural "aquamarine and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de aguamarina y oro" +msgstr[1] "anillos de aguamarina y oro" +msgstr[2] "anillos de aguamarina y oro" #. ~ Description for {'str': 'aquamarine and gold ring'} #: data/json/items/armor/jewelry.json @@ -63399,9 +63640,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and gold ring" msgid_plural "emerald and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de esmeralda y oro" +msgstr[1] "anillos de esmeralda y oro" +msgstr[2] "anillos de esmeralda y oro" #. ~ Description for {'str': 'emerald and gold ring'} #: data/json/items/armor/jewelry.json @@ -63431,9 +63672,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and gold ring" msgid_plural "ruby and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de rubí y oro" +msgstr[1] "anillos de rubí y oro" +msgstr[2] "anillos de rubí y oro" #. ~ Description for {'str': 'ruby and gold ring'} #: data/json/items/armor/jewelry.json @@ -63447,9 +63688,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and gold ring" msgid_plural "peridot and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de peridoto y oro" +msgstr[1] "anillos de peridoto y oro" +msgstr[2] "anillos de peridoto y oro" #. ~ Description for {'str': 'peridot and gold ring'} #: data/json/items/armor/jewelry.json @@ -63463,9 +63704,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and gold ring" msgid_plural "sapphire and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de zafiro y oro" +msgstr[1] "anillos de zafiro y oro" +msgstr[2] "anillos de zafiro y oro" #. ~ Description for {'str': 'sapphire and gold ring'} #: data/json/items/armor/jewelry.json @@ -63479,9 +63720,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and gold ring" msgid_plural "tourmaline and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de turmalina y oro" +msgstr[1] "anillos de turmalina y oro" +msgstr[2] "anillos de turmalina y oro" #. ~ Description for {'str': 'tourmaline and gold ring'} #: data/json/items/armor/jewelry.json @@ -63495,9 +63736,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and gold ring" msgid_plural "citrine and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de citrino y oro" +msgstr[1] "anillos de citrino y oro" +msgstr[2] "anillos de citrino y oro" #. ~ Description for {'str': 'citrine and gold ring'} #: data/json/items/armor/jewelry.json @@ -63511,9 +63752,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and gold ring" msgid_plural "blue topaz and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de topacio azul y oro" +msgstr[1] "anillos de topacio azul y oro" +msgstr[2] "anillos de topacio azul y oro" #. ~ Description for {'str': 'blue topaz and gold ring'} #: data/json/items/armor/jewelry.json @@ -63527,9 +63768,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and gold ring" msgid_plural "opal and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de ópalo y oro" +msgstr[1] "anillos de ópalo y oro" +msgstr[2] "anillos de ópalo y oro" #. ~ Description for {'str': 'opal and gold ring'} #: data/json/items/armor/jewelry.json @@ -63543,9 +63784,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and gold ring" msgid_plural "pearl and gold rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de perla y oro" +msgstr[1] "anillos de perla y oro" +msgstr[2] "anillos de perla y oro" #. ~ Description for {'str': 'pearl and gold ring'} #: data/json/items/armor/jewelry.json @@ -63559,9 +63800,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and silver ring" msgid_plural "diamond and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de diamante y plata" +msgstr[1] "anillos de diamante y plata" +msgstr[2] "anillos de diamante y plata" #. ~ Description for {'str': 'diamond and silver ring'} #: data/json/items/armor/jewelry.json @@ -63575,9 +63816,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and silver ring" msgid_plural "garnet and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de granate y plata" +msgstr[1] "anillos de granate y plata" +msgstr[2] "anillos de granate y plata" #. ~ Description for {'str': 'garnet and silver ring'} #: data/json/items/armor/jewelry.json @@ -63591,9 +63832,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and silver ring" msgid_plural "amethyst and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de amatista y plata" +msgstr[1] "anillos de amatista y plata" +msgstr[2] "anillos de amatista y plata" #. ~ Description for {'str': 'amethyst and silver ring'} #: data/json/items/armor/jewelry.json @@ -63623,9 +63864,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and silver ring" msgid_plural "emerald and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de esmeralda y plata" +msgstr[1] "anillos de esmeralda y plata" +msgstr[2] "anillos de esmeralda y plata" #. ~ Description for {'str': 'emerald and silver ring'} #: data/json/items/armor/jewelry.json @@ -63639,9 +63880,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and silver ring" msgid_plural "alexandrite and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de alejandrita y plata" +msgstr[1] "anillos de alejandrita y plata" +msgstr[2] "anillos de alejandrita y plata" #. ~ Description for {'str': 'alexandrite and silver ring'} #: data/json/items/armor/jewelry.json @@ -63671,9 +63912,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and silver ring" msgid_plural "peridot and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de peridoto y plata" +msgstr[1] "anillos de peridoto y plata" +msgstr[2] "anillos de peridoto y plata" #. ~ Description for {'str': 'peridot and silver ring'} #: data/json/items/armor/jewelry.json @@ -63687,9 +63928,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and silver ring" msgid_plural "sapphire and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de zafiro y plata" +msgstr[1] "anillos de zafiro y plata" +msgstr[2] "anillos de zafiro y plata" #. ~ Description for {'str': 'sapphire and silver ring'} #: data/json/items/armor/jewelry.json @@ -63703,9 +63944,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and silver ring" msgid_plural "tourmaline and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de turmalina y plata" +msgstr[1] "anillos de turmalina y plata" +msgstr[2] "anillos de turmalina y plata" #. ~ Description for {'str': 'tourmaline and silver ring'} #: data/json/items/armor/jewelry.json @@ -63719,9 +63960,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and silver ring" msgid_plural "citrine and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de citrino y plata" +msgstr[1] "anillos de citrino y plata" +msgstr[2] "anillos de citrino y plata" #. ~ Description for {'str': 'citrine and silver ring'} #: data/json/items/armor/jewelry.json @@ -63735,9 +63976,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and silver ring" msgid_plural "blue topaz and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de topacio azul y plata" +msgstr[1] "anillos de topacio azul y plata" +msgstr[2] "anillos de topacio azul y plata" #. ~ Description for {'str': 'blue topaz and silver ring'} #: data/json/items/armor/jewelry.json @@ -63751,9 +63992,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and silver ring" msgid_plural "opal and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de ópalo y plata" +msgstr[1] "anillos de ópalo y plata" +msgstr[2] "anillos de ópalo y plata" #. ~ Description for {'str': 'opal and silver ring'} #: data/json/items/armor/jewelry.json @@ -63767,9 +64008,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and silver ring" msgid_plural "pearl and silver rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de perla y plata" +msgstr[1] "anillos de perla y plata" +msgstr[2] "anillos de perla y plata" #. ~ Description for {'str': 'pearl and silver ring'} #: data/json/items/armor/jewelry.json @@ -63783,9 +64024,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and platinum ring" msgid_plural "diamond and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de diamante y platino" +msgstr[1] "anillos de diamante y platino" +msgstr[2] "anillos de diamante y platino" #. ~ Description for {'str': 'diamond and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63799,9 +64040,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and platinum ring" msgid_plural "garnet and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de granate y platino" +msgstr[1] "anillos de granate y platino" +msgstr[2] "anillos de granate y platino" #. ~ Description for {'str': 'garnet and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63815,9 +64056,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and platinum ring" msgid_plural "amethyst and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de amatista y platino" +msgstr[1] "anillos de amatista y platino" +msgstr[2] "anillos de amatista y platino" #. ~ Description for {'str': 'amethyst and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63831,9 +64072,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum ring" msgid_plural "aquamarine and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de aguamarina y platino" +msgstr[1] "anillos de aguamarina y platino" +msgstr[2] "anillos de aguamarina y platino" #. ~ Description for {'str': 'aquamarine and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63847,9 +64088,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and platinum ring" msgid_plural "emerald and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de esmeralda y platino" +msgstr[1] "anillos de esmeralda y platino" +msgstr[2] "anillos de esmeralda y platino" #. ~ Description for {'str': 'emerald and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63863,9 +64104,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum ring" msgid_plural "alexandrite and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de alejandrita y platino" +msgstr[1] "anillos de alejandrita y platino" +msgstr[2] "anillos de alejandrita y platino" #. ~ Description for {'str': 'alexandrite and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63879,9 +64120,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and platinum ring" msgid_plural "ruby and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de rubí y platino" +msgstr[1] "anillos de rubí y platino" +msgstr[2] "anillos de rubí y platino" #. ~ Description for {'str': 'ruby and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63895,9 +64136,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and platinum ring" msgid_plural "peridot and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de peridoto y platino" +msgstr[1] "anillos de peridoto y platino" +msgstr[2] "anillos de peridoto y platino" #. ~ Description for {'str': 'peridot and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63911,9 +64152,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and platinum ring" msgid_plural "sapphire and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de zafiro y platino" +msgstr[1] "anillos de zafiro y platino" +msgstr[2] "anillos de zafiro y platino" #. ~ Description for {'str': 'sapphire and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63927,9 +64168,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum ring" msgid_plural "tourmaline and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de turmalina y platino" +msgstr[1] "anillos de turmalina y platino" +msgstr[2] "anillos de turmalina y platino" #. ~ Description for {'str': 'tourmaline and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63943,9 +64184,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and platinum ring" msgid_plural "citrine and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de citrino y platino" +msgstr[1] "anillos de citrino y platino" +msgstr[2] "anillos de citrino y platino" #. ~ Description for {'str': 'citrine and platinum ring'} #: data/json/items/armor/jewelry.json @@ -63975,9 +64216,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and platinum ring" msgid_plural "opal and platinum rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de ópalo y platino" +msgstr[1] "anillos de ópalo y platino" +msgstr[2] "anillos de ópalo y platino" #. ~ Description for {'str': 'opal and platinum ring'} #: data/json/items/armor/jewelry.json @@ -64007,9 +64248,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and gold bracelet" msgid_plural "diamond and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de diamante y oro" +msgstr[1] "pulseras de diamante y oro" +msgstr[2] "pulseras de diamante y oro" #. ~ Description for {'str': 'diamond and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64023,9 +64264,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and gold bracelet" msgid_plural "garnet and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de granate y oro" +msgstr[1] "pulseras de granate y oro" +msgstr[2] "pulseras de granate y oro" #. ~ Description for {'str': 'garnet and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64039,9 +64280,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and gold bracelet" msgid_plural "amethyst and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de amatista y oro" +msgstr[1] "pulseras de amatista y oro" +msgstr[2] "pulseras de amatista y oro" #. ~ Description for {'str': 'amethyst and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64055,9 +64296,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and gold bracelet" msgid_plural "aquamarine and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de aguamarina y oro" +msgstr[1] "pulseras de aguamarina y oro" +msgstr[2] "pulseras de aguamarina y oro" #. ~ Description for {'str': 'aquamarine and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64071,9 +64312,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and gold bracelet" msgid_plural "emerald and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de esmeralda y oro" +msgstr[1] "pulseras de esmeralda y oro" +msgstr[2] "pulseras de esmeralda y oro" #. ~ Description for {'str': 'emerald and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64087,9 +64328,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and gold bracelet" msgid_plural "alexandrite and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de alejandrita y oro" +msgstr[1] "pulseras de alejandrita y oro" +msgstr[2] "pulseras de alejandrita y oro" #. ~ Description for {'str': 'alexandrite and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64103,9 +64344,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and gold bracelet" msgid_plural "ruby and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de rubí y oro" +msgstr[1] "pulseras de rubí y oro" +msgstr[2] "pulseras de rubí y oro" #. ~ Description for {'str': 'ruby and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64119,9 +64360,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and gold bracelet" msgid_plural "peridot and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de peridoto y oro" +msgstr[1] "pulseras de peridoto y oro" +msgstr[2] "pulseras de peridoto y oro" #. ~ Description for {'str': 'peridot and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64135,9 +64376,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and gold bracelet" msgid_plural "sapphire and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de zafiro y oro" +msgstr[1] "pulseras de zafiro y oro" +msgstr[2] "pulseras de zafiro y oro" #. ~ Description for {'str': 'sapphire and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64151,9 +64392,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and gold bracelet" msgid_plural "tourmaline and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de turmalina y oro" +msgstr[1] "pulseras de turmalina y oro" +msgstr[2] "pulseras de turmalina y oro" #. ~ Description for {'str': 'tourmaline and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64167,9 +64408,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and gold bracelet" msgid_plural "citrine and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de citrino y oro" +msgstr[1] "pulseras de citrino y oro" +msgstr[2] "pulseras de citrino y oro" #. ~ Description for {'str': 'citrine and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64183,9 +64424,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and gold bracelet" msgid_plural "blue topaz and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de topacio azul y oro" +msgstr[1] "pulseras de topacio azul y oro" +msgstr[2] "pulseras de topacio azul y oro" #. ~ Description for {'str': 'blue topaz and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64199,9 +64440,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and gold bracelet" msgid_plural "opal and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de ópalo y oro" +msgstr[1] "pulseras de ópalo y oro" +msgstr[2] "pulseras de ópalo y oro" #. ~ Description for {'str': 'opal and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64215,9 +64456,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and gold bracelet" msgid_plural "pearl and gold bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de perla y oro" +msgstr[1] "pulseras de perla y oro" +msgstr[2] "pulseras de perla y oro" #. ~ Description for {'str': 'pearl and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -64231,9 +64472,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and silver bracelet" msgid_plural "diamond and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de diamante y plata" +msgstr[1] "pulseras de diamante y plata" +msgstr[2] "pulseras de diamante y plata" #. ~ Description for {'str': 'diamond and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64263,9 +64504,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and silver bracelet" msgid_plural "amethyst and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de amatista y plata" +msgstr[1] "pulseras de amatista y plata" +msgstr[2] "pulseras de amatista y plata" #. ~ Description for {'str': 'amethyst and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64279,9 +64520,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and silver bracelet" msgid_plural "aquamarine and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de aguamarina y plata" +msgstr[1] "pulseras de aguamarina y plata" +msgstr[2] "pulseras de aguamarina y plata" #. ~ Description for {'str': 'aquamarine and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64295,9 +64536,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and silver bracelet" msgid_plural "emerald and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de esmeralda y plata" +msgstr[1] "pulseras de esmeralda y plata" +msgstr[2] "pulseras de esmeralda y plata" #. ~ Description for {'str': 'emerald and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64311,9 +64552,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and silver bracelet" msgid_plural "alexandrite and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de alejandrita y plata" +msgstr[1] "pulseras de alejandrita y plata" +msgstr[2] "pulseras de alejandrita y plata" #. ~ Description for {'str': 'alexandrite and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64327,9 +64568,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and silver bracelet" msgid_plural "ruby and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de rubí y plata" +msgstr[1] "pulseras de rubí y plata" +msgstr[2] "pulseras de rubí y plata" #. ~ Description for {'str': 'ruby and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64343,9 +64584,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and silver bracelet" msgid_plural "peridot and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de peridoto y plata" +msgstr[1] "pulseras de peridoto y plata" +msgstr[2] "pulseras de peridoto y plata" #. ~ Description for {'str': 'peridot and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64359,9 +64600,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and silver bracelet" msgid_plural "sapphire and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de zafiro y plata" +msgstr[1] "pulseras de zafiro y plata" +msgstr[2] "pulseras de zafiro y plata" #. ~ Description for {'str': 'sapphire and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64375,9 +64616,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and silver bracelet" msgid_plural "tourmaline and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de turmalina y plata" +msgstr[1] "pulseras de turmalina y plata" +msgstr[2] "pulseras de turmalina y plata" #. ~ Description for {'str': 'tourmaline and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64391,9 +64632,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and silver bracelet" msgid_plural "citrine and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de citrino y plata" +msgstr[1] "pulseras de citrino y plata" +msgstr[2] "pulseras de citrino y plata" #. ~ Description for {'str': 'citrine and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64407,9 +64648,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and silver bracelet" msgid_plural "blue topaz and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de topacio azul y plata" +msgstr[1] "pulseras de topacio azul y plata" +msgstr[2] "pulseras de topacio azul y plata" #. ~ Description for {'str': 'blue topaz and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64423,9 +64664,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and silver bracelet" msgid_plural "opal and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de ópalo y plata" +msgstr[1] "pulseras de ópalo y plata" +msgstr[2] "pulseras de ópalo y plata" #. ~ Description for {'str': 'opal and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64439,9 +64680,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and silver bracelet" msgid_plural "pearl and silver bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de perla y plata" +msgstr[1] "pulseras de perla y plata" +msgstr[2] "pulseras de perla y plata" #. ~ Description for {'str': 'pearl and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -64471,9 +64712,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and platinum bracelet" msgid_plural "garnet and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de granate y platino" +msgstr[1] "pulseras de granate y platino" +msgstr[2] "pulseras de granate y platino" #. ~ Description for {'str': 'garnet and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64487,9 +64728,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and platinum bracelet" msgid_plural "amethyst and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de amatista y platino" +msgstr[1] "pulseras de amatista y platino" +msgstr[2] "pulseras de amatista y platino" #. ~ Description for {'str': 'amethyst and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64503,9 +64744,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum bracelet" msgid_plural "aquamarine and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de aguamarina y platino" +msgstr[1] "pulseras de aguamarina y platino" +msgstr[2] "pulseras de aguamarina y platino" #. ~ Description for {'str': 'aquamarine and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64519,9 +64760,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and platinum bracelet" msgid_plural "emerald and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de esmeralda y platino" +msgstr[1] "pulseras de esmeralda y platino" +msgstr[2] "pulseras de esmeralda y platino" #. ~ Description for {'str': 'emerald and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64535,9 +64776,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum bracelet" msgid_plural "alexandrite and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de alejandrita y platino" +msgstr[1] "pulseras de alejandrita y platino" +msgstr[2] "pulseras de alejandrita y platino" #. ~ Description for {'str': 'alexandrite and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64551,9 +64792,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and platinum bracelet" msgid_plural "ruby and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de rubí y platino" +msgstr[1] "pulseras de rubí y platino" +msgstr[2] "pulseras de rubí y platino" #. ~ Description for {'str': 'ruby and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64567,9 +64808,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and platinum bracelet" msgid_plural "peridot and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de peridoto y platino" +msgstr[1] "pulseras de peridoto y platino" +msgstr[2] "pulseras de peridoto y platino" #. ~ Description for {'str': 'peridot and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64583,9 +64824,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and platinum bracelet" msgid_plural "sapphire and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de zafiro y platino" +msgstr[1] "pulseras de zafiro y platino" +msgstr[2] "pulseras de zafiro y platino" #. ~ Description for {'str': 'sapphire and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64599,9 +64840,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum bracelet" msgid_plural "tourmaline and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de turmalina y platino" +msgstr[1] "pulseras de turmalina y platino" +msgstr[2] "pulseras de turmalina y platino" #. ~ Description for {'str': 'tourmaline and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64615,9 +64856,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and platinum bracelet" msgid_plural "citrine and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de citrino y platino" +msgstr[1] "pulseras de citrino y platino" +msgstr[2] "pulseras de citrino y platino" #. ~ Description for {'str': 'citrine and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64631,9 +64872,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum bracelet" msgid_plural "blue topaz and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de topacio azul y platino" +msgstr[1] "pulseras de topacio azul y platino" +msgstr[2] "pulseras de topacio azul y platino" #. ~ Description for {'str': 'blue topaz and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64647,9 +64888,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and platinum bracelet" msgid_plural "opal and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de ópalo y platino" +msgstr[1] "pulseras de ópalo y platino" +msgstr[2] "pulseras de ópalo y platino" #. ~ Description for {'str': 'opal and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64663,9 +64904,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and platinum bracelet" msgid_plural "pearl and platinum bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de perla y platino" +msgstr[1] "pulseras de perla y platino" +msgstr[2] "pulseras de perla y platino" #. ~ Description for {'str': 'pearl and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -64679,9 +64920,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and gold necklace" msgid_plural "garnet and gold necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "collar de granate y oro" +msgstr[1] "collares de granate y oro" +msgstr[2] "collares de granate y oro" #. ~ Description for {'str': 'garnet and gold necklace'} #: data/json/items/armor/jewelry.json @@ -64695,9 +64936,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and gold pendant necklace" msgid_plural "diamond and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de diamante y oro" +msgstr[1] "colgantes de diamante y oro" +msgstr[2] "colgantes de diamante y oro" #. ~ Description for {'str': 'diamond and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64711,9 +64952,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and gold pendant necklace" msgid_plural "amethyst and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de amatista y oro" +msgstr[1] "colgantes de amatista y oro" +msgstr[2] "colgantes de amatista y oro" #. ~ Description for {'str': 'amethyst and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64727,9 +64968,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and gold pendant necklace" msgid_plural "aquamarine and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de aguamarina y oro" +msgstr[1] "colgantes de aguamarina y oro" +msgstr[2] "colgantes de aguamarina y oro" #. ~ Description for {'str': 'aquamarine and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64743,9 +64984,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and gold pendant necklace" msgid_plural "emerald and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de esmeralda y oro" +msgstr[1] "colgantes de esmeralda y oro" +msgstr[2] "colgantes de esmeralda y oro" #. ~ Description for {'str': 'emerald and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64759,9 +65000,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and gold pendant necklace" msgid_plural "alexandrite and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de alejandrita y oro" +msgstr[1] "colgantes de alejandrita y oro" +msgstr[2] "colgantes de alejandrita y oro" #. ~ Description for {'str': 'alexandrite and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64775,9 +65016,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and gold pendant necklace" msgid_plural "ruby and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de rubí y oro" +msgstr[1] "colgantes de rubí y oro" +msgstr[2] "colgantes de rubí y oro" #. ~ Description for {'str': 'ruby and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64791,9 +65032,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and gold pendant necklace" msgid_plural "peridot and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de peridoto y oro" +msgstr[1] "colgantes de peridoto y oro" +msgstr[2] "colgantes de peridoto y oro" #. ~ Description for {'str': 'peridot and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64807,9 +65048,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and gold pendant necklace" msgid_plural "sapphire and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de zafiro y oro" +msgstr[1] "colgantes de zafiro y oro" +msgstr[2] "colgantes de zafiro y oro" #. ~ Description for {'str': 'sapphire and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64823,9 +65064,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and gold pendant necklace" msgid_plural "tourmaline and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de turmalina y oro" +msgstr[1] "colgantes de turmalina y oro" +msgstr[2] "colgantes de turmalina y oro" #. ~ Description for {'str': 'tourmaline and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64839,9 +65080,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and gold pendant necklace" msgid_plural "citrine and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de citrino y oro" +msgstr[1] "colgantes de citrino y oro" +msgstr[2] "colgantes de citrino y oro" #. ~ Description for {'str': 'citrine and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64855,9 +65096,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and gold pendant necklace" msgid_plural "blue topaz and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de topacio azul y oro" +msgstr[1] "colgantes de topacio azul y oro" +msgstr[2] "colgantes de topacio azul y oro" #. ~ Description for {'str': 'blue topaz and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64871,9 +65112,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and gold pendant necklace" msgid_plural "opal and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de ópalo y oro" +msgstr[1] "colgantes de ópalo y oro" +msgstr[2] "colgantes de ópalo y oro" #. ~ Description for {'str': 'opal and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64887,9 +65128,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and gold pendant necklace" msgid_plural "pearl and gold pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de perla y oro" +msgstr[1] "colgantes de perla y oro" +msgstr[2] "colgantes de perla y oro" #. ~ Description for {'str': 'pearl and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64903,9 +65144,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and silver necklace" msgid_plural "garnet and silver necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de granate y plata" +msgstr[1] "colgantes de granate y plata" +msgstr[2] "colgantes de granate y plata" #. ~ Description for {'str': 'garnet and silver necklace'} #: data/json/items/armor/jewelry.json @@ -64919,9 +65160,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and silver pendant necklace" msgid_plural "diamond and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de granate y plata" +msgstr[1] "colgantes de granate y plata" +msgstr[2] "colgantes de granate y plata" #. ~ Description for {'str': 'diamond and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64935,9 +65176,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and silver pendant necklace" msgid_plural "amethyst and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de amatista y plata" +msgstr[1] "colgantes de amatista y plata" +msgstr[2] "colgantes de amatista y plata" #. ~ Description for {'str': 'amethyst and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64951,9 +65192,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and silver pendant necklace" msgid_plural "aquamarine and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de aguamarina y plata" +msgstr[1] "colgantes de aguamarina y plata" +msgstr[2] "colgantes de aguamarina y plata" #. ~ Description for {'str': 'aquamarine and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64967,9 +65208,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and silver pendant necklace" msgid_plural "emerald and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de esmeralda y plata" +msgstr[1] "colgantes de esmeralda y plata" +msgstr[2] "colgantes de esmeralda y plata" #. ~ Description for {'str': 'emerald and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64983,9 +65224,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and silver pendant necklace" msgid_plural "alexandrite and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de alejandrita y plata" +msgstr[1] "colgantes de alejandrita y plata" +msgstr[2] "colgantes de alejandrita y plata" #. ~ Description for {'str': 'alexandrite and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -64999,9 +65240,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and silver pendant necklace" msgid_plural "ruby and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de rubí y plata" +msgstr[1] "colgantes de rubí y plata" +msgstr[2] "colgantes de rubí y plata" #. ~ Description for {'str': 'ruby and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65015,9 +65256,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and silver pendant necklace" msgid_plural "peridot and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de peridoto y plata" +msgstr[1] "colgantes de peridoto y plata" +msgstr[2] "colgantes de peridoto y plata" #. ~ Description for {'str': 'peridot and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65031,9 +65272,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and silver pendant necklace" msgid_plural "sapphire and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de zafiro y plata" +msgstr[1] "colgantes de zafiro y plata" +msgstr[2] "colgantes de zafiro y plata" #. ~ Description for {'str': 'sapphire and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65047,9 +65288,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and silver pendant necklace" msgid_plural "tourmaline and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de turmalina y plata" +msgstr[1] "colgantes de turmalina y plata" +msgstr[2] "colgantes de turmalina y plata" #. ~ Description for {'str': 'tourmaline and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65063,9 +65304,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and silver pendant necklace" msgid_plural "citrine and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de citrino y plata" +msgstr[1] "colgantes de citrino y plata" +msgstr[2] "colgantes de citrino y plata" #. ~ Description for {'str': 'citrine and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65079,9 +65320,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and silver pendant necklace" msgid_plural "blue topaz and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de topacio azul y plata" +msgstr[1] "colgantes de topacio azul y plata" +msgstr[2] "colgantes de topacio azul y plata" #. ~ Description for {'str': 'blue topaz and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65095,9 +65336,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and silver pendant necklace" msgid_plural "opal and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de ópalo y plata" +msgstr[1] "colgantes de ópalo y plata" +msgstr[2] "colgantes de ópalo y plata" #. ~ Description for {'str': 'opal and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65111,9 +65352,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and silver pendant necklace" msgid_plural "pearl and silver pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de perla y plata" +msgstr[1] "colgantes de perla y plata" +msgstr[2] "colgantes de perla y plata" #. ~ Description for {'str': 'pearl and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65127,9 +65368,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and platinum necklace" msgid_plural "garnet and platinum necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de granate y platino" +msgstr[1] "colgantes de granate y platino" +msgstr[2] "colgantes de granate y platino" #. ~ Description for {'str': 'garnet and platinum necklace'} #: data/json/items/armor/jewelry.json @@ -65143,9 +65384,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diamond and platinum pendant necklace" msgid_plural "diamond and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de diamante y platino" +msgstr[1] "colgantes de diamante y platino" +msgstr[2] "colgantes de diamante y platino" #. ~ Description for {'str': 'diamond and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65159,9 +65400,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "amethyst and platinum pendant necklace" msgid_plural "amethyst and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de amatista y platino" +msgstr[1] "colgantes de amatista y platino" +msgstr[2] "colgantes de amatista y platino" #. ~ Description for {'str': 'amethyst and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65175,9 +65416,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum pendant necklace" msgid_plural "aquamarine and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de aguamarina y platino" +msgstr[1] "colgantes de aguamarina y platino" +msgstr[2] "colgantes de aguamarina y platino" #. ~ Description for {'str': 'aquamarine and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65191,9 +65432,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "emerald and platinum pendant necklace" msgid_plural "emerald and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de esmeralda y platino" +msgstr[1] "colgantes de esmeralda y platino" +msgstr[2] "colgantes de esmeralda y platino" #. ~ Description for {'str': 'emerald and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65207,9 +65448,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum pendant necklace" msgid_plural "alexandrite and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de alejandrita y platino" +msgstr[1] "colgantes de alejandrita y platino" +msgstr[2] "colgantes de alejandrita y platino" #. ~ Description for {'str': 'alexandrite and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65223,9 +65464,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "ruby and platinum pendant necklace" msgid_plural "ruby and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de rubí y platino" +msgstr[1] "colgantes de rubí y platino" +msgstr[2] "colgantes de rubí y platino" #. ~ Description for {'str': 'ruby and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65239,9 +65480,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "peridot and platinum pendant necklace" msgid_plural "peridot and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de peridoto y platino" +msgstr[1] "colgantes de peridoto y platino" +msgstr[2] "colgantes de peridoto y platino" #. ~ Description for {'str': 'peridot and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65255,9 +65496,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "sapphire and platinum pendant necklace" msgid_plural "sapphire and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de zafiro y platino" +msgstr[1] "colgantes de zafiro y platino" +msgstr[2] "colgantes de zafiro y platino" #. ~ Description for {'str': 'sapphire and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65271,9 +65512,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum pendant necklace" msgid_plural "tourmaline and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de turmalina y platino" +msgstr[1] "colgantes de turmalina y platino" +msgstr[2] "colgantes de turmalina y platino" #. ~ Description for {'str': 'tourmaline and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65287,9 +65528,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "citrine and platinum pendant necklace" msgid_plural "citrine and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de citrino y platino" +msgstr[1] "colgantes de citrino y platino" +msgstr[2] "colgantes de citrino y platino" #. ~ Description for {'str': 'citrine and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65303,9 +65544,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum pendant necklace" msgid_plural "blue topaz and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de topacio azul y platino" +msgstr[1] "colgantes de topacio azul y platino" +msgstr[2] "colgantes de topacio azul y platino" #. ~ Description for {'str': 'blue topaz and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65319,9 +65560,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "opal and platinum pendant necklace" msgid_plural "opal and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de ópalo y platino" +msgstr[1] "colgantes de ópalo y platino" +msgstr[2] "colgantes de ópalo y platino" #. ~ Description for {'str': 'opal and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65335,9 +65576,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pearl and platinum pendant necklace" msgid_plural "pearl and platinum pendant necklaces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colgante de perla y platino" +msgstr[1] "colgantes de perla y platino" +msgstr[2] "colgantes de perla y platino" #. ~ Description for {'str': 'pearl and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -65351,9 +65592,9 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "garnet and platinum tiara" msgid_plural "garnet and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de granate y platino" +msgstr[1] "tiaras de granate y platino" +msgstr[2] "tiaras de granate y platino" #. ~ Description for {'str': 'garnet and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65363,9 +65604,9 @@ msgstr "Es una tiara brillante de platino, adornada con granates." #: data/json/items/armor/jewelry.json msgid "diamond and platinum tiara" msgid_plural "diamond and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de diamante y platino" +msgstr[1] "tiaras de diamante y platino" +msgstr[2] "tiaras de diamante y platino" #. ~ Description for {'str': 'diamond and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65375,9 +65616,9 @@ msgstr "Es una tiara brillante de platino, adornada con diamantes." #: data/json/items/armor/jewelry.json msgid "amethyst and platinum tiara" msgid_plural "amethyst and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de amatista y platino" +msgstr[1] "tiaras de amatista y platino" +msgstr[2] "tiaras de amatista y platino" #. ~ Description for {'str': 'amethyst and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65387,9 +65628,9 @@ msgstr "Es una tiara brillante de platino, adornada con amatista." #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum tiara" msgid_plural "aquamarine and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de aguamarina y platino" +msgstr[1] "tiaras de aguamarina y platino" +msgstr[2] "tiaras de aguamarina y platino" #. ~ Description for {'str': 'aquamarine and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65399,9 +65640,9 @@ msgstr "Es una tiara brillante de platino, adornada con aguamarina." #: data/json/items/armor/jewelry.json msgid "emerald and platinum tiara" msgid_plural "emerald and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de esmeralda y platino" +msgstr[1] "tiaras de esmeralda y platino" +msgstr[2] "tiaras de esmeralda y platino" #. ~ Description for {'str': 'emerald and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65411,9 +65652,9 @@ msgstr "Es una tiara brillante de platino, adornada con esmeraldas." #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum tiara" msgid_plural "alexandrite and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de alejandrita y platino" +msgstr[1] "tiaras de alejandrita y platino" +msgstr[2] "tiaras de alejandrita y platino" #. ~ Description for {'str': 'alexandrite and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65423,9 +65664,9 @@ msgstr "Es una tiara brillante de platino, adornada con alejandritas." #: data/json/items/armor/jewelry.json msgid "ruby and platinum tiara" msgid_plural "ruby and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de rubí y platino" +msgstr[1] "tiaras de rubí y platino" +msgstr[2] "tiaras de rubí y platino" #. ~ Description for {'str': 'ruby and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65435,9 +65676,9 @@ msgstr "Es una tiara brillante de platino, adornada con rubíes." #: data/json/items/armor/jewelry.json msgid "peridot and platinum tiara" msgid_plural "peridot and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de peridoto y platino" +msgstr[1] "tiaras de peridoto y platino" +msgstr[2] "tiaras de peridoto y platino" #. ~ Description for {'str': 'peridot and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65447,9 +65688,9 @@ msgstr "Es una tiara brillante de platino, adornada con peridotos." #: data/json/items/armor/jewelry.json msgid "sapphire and platinum tiara" msgid_plural "sapphire and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de zafiro y platino" +msgstr[1] "tiaras de zafiro y platino" +msgstr[2] "tiaras de zafiro y platino" #. ~ Description for {'str': 'sapphire and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65459,9 +65700,9 @@ msgstr "Es una tiara brillante de platino, adornada con zafiros." #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum tiara" msgid_plural "tourmaline and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de turmalina y platino" +msgstr[1] "tiaras de turmalina y platino" +msgstr[2] "tiaras de turmalina y platino" #. ~ Description for {'str': 'tourmaline and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65471,9 +65712,9 @@ msgstr "Es una tiara brillante de platino, adornada con turmalinas." #: data/json/items/armor/jewelry.json msgid "citrine and platinum tiara" msgid_plural "citrine and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de citrino y platino" +msgstr[1] "tiaras de citrino y platino" +msgstr[2] "tiaras de citrino y platino" #. ~ Description for {'str': 'citrine and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65483,9 +65724,9 @@ msgstr "Es una tiara brillante de platino, adornada con citrinos." #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum tiara" msgid_plural "blue topaz and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de topacio azul y platino" +msgstr[1] "tiaras de topacio azul y platino" +msgstr[2] "tiaras de topacio azul y platino" #. ~ Description for {'str': 'blue topaz and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65495,9 +65736,9 @@ msgstr "Es una tiara brillante de platino, adornada con topacio azul." #: data/json/items/armor/jewelry.json msgid "opal and platinum tiara" msgid_plural "opal and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de ópalo y platino" +msgstr[1] "tiaras de ópalo y platino" +msgstr[2] "tiaras de ópalo y platino" #. ~ Description for {'str': 'opal and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65507,9 +65748,9 @@ msgstr "Es una tiara brillante de platino, adornada con ópalos." #: data/json/items/armor/jewelry.json msgid "pearl and platinum tiara" msgid_plural "pearl and platinum tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de perla y platino" +msgstr[1] "tiaras de perla y platino" +msgstr[2] "tiaras de perla y platino" #. ~ Description for {'str': 'pearl and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -65519,9 +65760,9 @@ msgstr "Es una tiara brillante de platino, adornada con perlas." #: data/json/items/armor/jewelry.json msgid "garnet and gold tiara" msgid_plural "garnet and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de granate y oro" +msgstr[1] "tiaras de granate y oro" +msgstr[2] "tiaras de granate y oro" #. ~ Description for {'str': 'garnet and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65531,9 +65772,9 @@ msgstr "Es una tiara brillante de oro, adornada con granates." #: data/json/items/armor/jewelry.json msgid "diamond and gold tiara" msgid_plural "diamond and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de diamante y oro" +msgstr[1] "tiaras de diamante y oro" +msgstr[2] "tiaras de diamante y oro" #. ~ Description for {'str': 'diamond and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65543,9 +65784,9 @@ msgstr "Es una tiara brillante de oro, adornada con diamantes." #: data/json/items/armor/jewelry.json msgid "amethyst and gold tiara" msgid_plural "amethyst and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de amatista y oro" +msgstr[1] "tiaras de amatista y oro" +msgstr[2] "tiaras de amatista y oro" #. ~ Description for {'str': 'amethyst and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65555,9 +65796,9 @@ msgstr "Es una tiara brillante de oro, adornada con amatista." #: data/json/items/armor/jewelry.json msgid "aquamarine and gold tiara" msgid_plural "aquamarine and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de aguamarina y oro" +msgstr[1] "tiaras de aguamarina y oro" +msgstr[2] "tiaras de aguamarina y oro" #. ~ Description for {'str': 'aquamarine and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65567,9 +65808,9 @@ msgstr "Es una tiara brillante de oro, adornada con aguamarina." #: data/json/items/armor/jewelry.json msgid "emerald and gold tiara" msgid_plural "emerald and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de esmeralda y oro" +msgstr[1] "tiaras de esmeralda y oro" +msgstr[2] "tiaras de esmeralda y oro" #. ~ Description for {'str': 'emerald and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65579,9 +65820,9 @@ msgstr "Es una tiara brillante de oro, adornada con esmeraldas." #: data/json/items/armor/jewelry.json msgid "alexandrite and gold tiara" msgid_plural "alexandrite and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de alejandrita y oro" +msgstr[1] "tiaras de alejandrita y oro" +msgstr[2] "tiaras de alejandrita y oro" #. ~ Description for {'str': 'alexandrite and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65591,9 +65832,9 @@ msgstr "Es una tiara brillante de oro, adornada con alejandritas." #: data/json/items/armor/jewelry.json msgid "ruby and gold tiara" msgid_plural "ruby and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de rubí y oro" +msgstr[1] "tiaras de rubí y oro" +msgstr[2] "tiaras de rubí y oro" #. ~ Description for {'str': 'ruby and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65603,9 +65844,9 @@ msgstr "Es una tiara brillante de oro, adornada con rubíes." #: data/json/items/armor/jewelry.json msgid "peridot and gold tiara" msgid_plural "peridot and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de peridoto y oro" +msgstr[1] "tiaras de peridoto y oro" +msgstr[2] "tiaras de peridoto y oro" #. ~ Description for {'str': 'peridot and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65615,9 +65856,9 @@ msgstr "Es una tiara brillante de oro, adornada con peridotos." #: data/json/items/armor/jewelry.json msgid "sapphire and gold tiara" msgid_plural "sapphire and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de zafiro y oro" +msgstr[1] "tiaras de zafiro y oro" +msgstr[2] "tiaras de zafiro y oro" #. ~ Description for {'str': 'sapphire and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65627,9 +65868,9 @@ msgstr "Es una tiara brillante de oro, adornada con zafiros." #: data/json/items/armor/jewelry.json msgid "tourmaline and gold tiara" msgid_plural "tourmaline and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de turmalina y oro" +msgstr[1] "tiaras de turmalina y oro" +msgstr[2] "tiaras de turmalina y oro" #. ~ Description for {'str': 'tourmaline and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65639,9 +65880,9 @@ msgstr "Es una tiara brillante de oro, adornada con turmalinas." #: data/json/items/armor/jewelry.json msgid "citrine and gold tiara" msgid_plural "citrine and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de citrino y oro" +msgstr[1] "tiaras de citrino y oro" +msgstr[2] "tiaras de citrino y oro" #. ~ Description for {'str': 'citrine and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65651,9 +65892,9 @@ msgstr "Es una tiara brillante de oro, adornada con citrinos." #: data/json/items/armor/jewelry.json msgid "blue topaz and gold tiara" msgid_plural "blue topaz and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de topacio azul y oro" +msgstr[1] "tiaras de topacio azul y oro" +msgstr[2] "tiaras de topacio azul y oro" #. ~ Description for {'str': 'blue topaz and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65663,9 +65904,9 @@ msgstr "Es una tiara brillante de oro, adornada con topacio azul." #: data/json/items/armor/jewelry.json msgid "opal and gold tiara" msgid_plural "opal and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de ópalo y oro" +msgstr[1] "tiaras de ópalo y oro" +msgstr[2] "tiaras de ópalo y oro" #. ~ Description for {'str': 'opal and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65675,9 +65916,9 @@ msgstr "Es una tiara brillante de oro, adornada con ópalos." #: data/json/items/armor/jewelry.json msgid "pearl and gold tiara" msgid_plural "pearl and gold tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de perla y oro" +msgstr[1] "tiaras de perla y oro" +msgstr[2] "tiaras de perla y oro" #. ~ Description for {'str': 'pearl and gold tiara'} #: data/json/items/armor/jewelry.json @@ -65687,9 +65928,9 @@ msgstr "Es una tiara brillante de oro, adornada con perlas." #: data/json/items/armor/jewelry.json msgid "garnet and silver tiara" msgid_plural "garnet and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de granate y plata" +msgstr[1] "tiaras de granate y plata" +msgstr[2] "tiaras de granate y plata" #. ~ Description for {'str': 'garnet and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65699,9 +65940,9 @@ msgstr "Es una tiara brillante de plata, adornada con granates." #: data/json/items/armor/jewelry.json msgid "diamond and silver tiara" msgid_plural "diamond and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de diamante y plata" +msgstr[1] "tiaras de diamante y plata" +msgstr[2] "tiaras de diamante y plata" #. ~ Description for {'str': 'diamond and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65711,9 +65952,9 @@ msgstr "Es una tiara brillante de plata, adornada con diamantes." #: data/json/items/armor/jewelry.json msgid "amethyst and silver tiara" msgid_plural "amethyst and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de amatista y plata" +msgstr[1] "tiaras de amatista y plata" +msgstr[2] "tiaras de amatista y plata" #. ~ Description for {'str': 'amethyst and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65723,9 +65964,9 @@ msgstr "Es una tiara brillante de plata, adornada con amatista." #: data/json/items/armor/jewelry.json msgid "aquamarine and silver tiara" msgid_plural "aquamarine and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de aguamarina y plata" +msgstr[1] "tiaras de aguamarina y plata" +msgstr[2] "tiaras de aguamarina y plata" #. ~ Description for {'str': 'aquamarine and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65735,9 +65976,9 @@ msgstr "Es una tiara brillante de plata, adornada con aguamarina." #: data/json/items/armor/jewelry.json msgid "emerald and silver tiara" msgid_plural "emerald and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de esmeralda y plata" +msgstr[1] "tiaras de esmeralda y plata" +msgstr[2] "tiaras de esmeralda y plata" #. ~ Description for {'str': 'emerald and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65747,9 +65988,9 @@ msgstr "Es una tiara brillante de plata, adornada con esmeraldas." #: data/json/items/armor/jewelry.json msgid "alexandrite and silver tiara" msgid_plural "alexandrite and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de alejandrita y plata" +msgstr[1] "tiaras de alejandrita y plata" +msgstr[2] "tiaras de alejandrita y plata" #. ~ Description for {'str': 'alexandrite and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65759,9 +66000,9 @@ msgstr "Es una tiara brillante de plata, adornada con alejandritas." #: data/json/items/armor/jewelry.json msgid "ruby and silver tiara" msgid_plural "ruby and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de rubí y plata" +msgstr[1] "tiaras de rubí y plata" +msgstr[2] "tiaras de rubí y plata" #. ~ Description for {'str': 'ruby and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65771,9 +66012,9 @@ msgstr "Es una tiara brillante de plata, adornada con rubíes." #: data/json/items/armor/jewelry.json msgid "peridot and silver tiara" msgid_plural "peridot and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de peridoto y plata" +msgstr[1] "tiaras de peridoto y plata" +msgstr[2] "tiaras de peridoto y plata" #. ~ Description for {'str': 'peridot and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65783,9 +66024,9 @@ msgstr "Es una tiara brillante de plata, adornada con peridotos." #: data/json/items/armor/jewelry.json msgid "sapphire and silver tiara" msgid_plural "sapphire and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de zafiro y plata" +msgstr[1] "tiaras de zafiro y plata" +msgstr[2] "tiaras de zafiro y plata" #. ~ Description for {'str': 'sapphire and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65795,9 +66036,9 @@ msgstr "Es una tiara brillante de plata, adornada con zafiros." #: data/json/items/armor/jewelry.json msgid "tourmaline and silver tiara" msgid_plural "tourmaline and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de turmalina y plata" +msgstr[1] "tiaras de turmalina y plata" +msgstr[2] "tiaras de turmalina y plata" #. ~ Description for {'str': 'tourmaline and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65807,9 +66048,9 @@ msgstr "Es una tiara brillante de plata, adornada con turmalinas." #: data/json/items/armor/jewelry.json msgid "citrine and silver tiara" msgid_plural "citrine and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de citrino y plata" +msgstr[1] "tiaras de citrino y plata" +msgstr[2] "tiaras de citrino y plata" #. ~ Description for {'str': 'citrine and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65819,9 +66060,9 @@ msgstr "Es una tiara brillante de plata, adornada con citrinos." #: data/json/items/armor/jewelry.json msgid "blue topaz and silver tiara" msgid_plural "blue topaz and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de topacio azul y plata" +msgstr[1] "tiaras de topacio azul y plata" +msgstr[2] "tiaras de topacio azul y plata" #. ~ Description for {'str': 'blue topaz and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65831,9 +66072,9 @@ msgstr "Es una tiara brillante de plata, adornada con topacio azul." #: data/json/items/armor/jewelry.json msgid "opal and silver tiara" msgid_plural "opal and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de ópalo y plata" +msgstr[1] "tiaras de ópalo y plata" +msgstr[2] "tiaras de ópalo y plata" #. ~ Description for {'str': 'opal and silver tiara'} #: data/json/items/armor/jewelry.json @@ -65843,9 +66084,9 @@ msgstr "Es una tiara brillante de plata, adornada con ópalos." #: data/json/items/armor/jewelry.json msgid "pearl and silver tiara" msgid_plural "pearl and silver tiaras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tiara de perla y plata" +msgstr[1] "tiaras de perla y plata" +msgstr[2] "tiaras de perla y plata" #. ~ Description for {'str': 'pearl and silver tiara'} #: data/json/items/armor/jewelry.json @@ -66028,9 +66269,9 @@ msgstr "" #: data/json/items/armor/legs_armor.json msgid "pair of scrap leg guards" msgid_plural "pairs of scrap leg guards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de perneras de chatarra" +msgstr[1] "pares de perneras de chatarra" +msgstr[2] "pares de perneras de chatarra" #. ~ Description for {'str': 'pair of scrap leg guards', 'str_pl': 'pairs of #. scrap leg guards'} @@ -66738,9 +66979,9 @@ msgstr "" #: data/json/items/armor/misc.json msgid "clown wig" msgid_plural "clown wigs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "peluca de payaso" +msgstr[1] "pelucas de payaso" +msgstr[2] "pelucas de payaso" #. ~ Description for {'str': 'clown wig'} #: data/json/items/armor/misc.json @@ -66750,9 +66991,9 @@ msgstr "Es una peluca colorida y ridícula ideal para un payaso." #: data/json/items/armor/misc.json msgid "clown nose" msgid_plural "clown noses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nariz de payaso" +msgstr[1] "narices de payaso" +msgstr[2] "narices de payaso" #. ~ Description for {'str': 'clown nose'} #: data/json/items/armor/misc.json @@ -66880,9 +67121,9 @@ msgstr "" #: data/json/items/armor/misc.json msgid "bow tie" msgid_plural "bow ties" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "moño" +msgstr[1] "moños" +msgstr[2] "moños" #. ~ Description for {'str': 'bow tie'} #: data/json/items/armor/misc.json @@ -66892,9 +67133,9 @@ msgstr "Es un moño negro común. Lo mejor es usarlo con un traje." #: data/json/items/armor/misc.json msgid "clip-on tie" msgid_plural "clip-on ties" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "corbata con gancho" +msgstr[1] "corbatas con gancho" +msgstr[2] "corbatas con gancho" #. ~ Description for {'str': 'clip-on tie'} #: data/json/items/armor/misc.json @@ -67137,9 +67378,9 @@ msgstr "" #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "pair of saddle bags" msgid_plural "pairs of saddle bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de bolsas de montura" +msgstr[1] "pares de bolsas de montura" +msgstr[2] "pares de bolsas de montura" #. ~ Description for {'str': 'pair of saddle bags', 'str_pl': 'pairs of saddle #. bags'} @@ -67776,9 +68017,9 @@ msgstr "" #: data/json/items/armor/scarfs.json msgid "headscarf" msgid_plural "headscarfs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "justka" +msgstr[1] "justkas" +msgstr[2] "justkas" #. ~ Description for {'str': 'headscarf'} #: data/json/items/armor/scarfs.json @@ -67807,9 +68048,9 @@ msgstr "" #: data/json/items/armor/scarfs.json msgid "cyan scarf" msgid_plural "cyan scarfs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bufanda turquesa" +msgstr[1] "bufandas turquesas" +msgstr[2] "bufandas turquesas" #. ~ Description for {'str': 'cyan scarf'} #: data/json/items/armor/scarfs.json @@ -67823,9 +68064,9 @@ msgstr "" #: data/json/items/armor/sheath.json msgid "axe ring holster" msgid_plural "axe ring holsters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aro para colgar hachas" +msgstr[1] "aros para colgar hachas" +msgstr[2] "aros para colgar hachas" #. ~ Use action holster_prompt for {'str': 'axe ring holster'}. #: data/json/items/armor/sheath.json @@ -68146,9 +68387,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "hiking backpack" msgid_plural "hiking backpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochila de excursión" +msgstr[1] "mochilas de excursión" +msgstr[2] "mochilas de excursión" #. ~ Description for {'str': 'hiking backpack'} #: data/json/items/armor/storage.json @@ -68189,9 +68430,9 @@ msgstr "Es una mochila pequeña de cuero. Buena capacidad y poca incomodidad." #: data/json/items/armor/storage.json msgid "large tactical backpack" msgid_plural "large tactical backpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochila táctica grande" +msgstr[1] "mochilas tácticas grandes" +msgstr[2] "mochilas tácticas grandes" #. ~ Description for {'str': 'large tactical backpack'} #: data/json/items/armor/storage.json @@ -68217,9 +68458,9 @@ msgstr "Una cesta de plástico pensada para almacenar y transportar ropa." #: data/json/items/armor/storage.json msgid "high-volume rucksack" msgid_plural "high-volume rucksacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochilón amplio" +msgstr[1] "mochilones amplios" +msgstr[2] "mochilones amplios" #. ~ Description for {'str': 'high-volume rucksack'} #: data/json/items/armor/storage.json @@ -68248,9 +68489,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "box backpack" msgid_plural "box backpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochila caja" +msgstr[1] "mochilas caja" +msgstr[2] "mochilas caja" #. ~ Description for {'str': 'box backpack'} #: data/json/items/armor/storage.json @@ -68274,9 +68515,9 @@ msgstr "Útil para llevar dinero, documentos, o contrabando." #: data/json/items/armor/storage.json msgid "violin case" msgid_plural "violin cases" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estuche de violín" +msgstr[1] "estuches de violín" +msgstr[2] "estuches de violín" #. ~ Description for {'str': 'violin case'} #: data/json/items/armor/storage.json @@ -68290,9 +68531,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "daypack" msgid_plural "daypacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochilita" +msgstr[1] "mochilitas" +msgstr[2] "mochilitas" #. ~ Description for {'str': 'daypack'} #: data/json/items/armor/storage.json @@ -68388,9 +68629,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "hide bag" msgid_plural "hide bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolso de pellejo" +msgstr[1] "bolsos de pellejo" +msgstr[2] "bolsos de pellejo" #. ~ Description for {'str': 'hide bag'} #: data/json/items/armor/storage.json @@ -68404,9 +68645,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "tainted hide bag" msgid_plural "tainted hide bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolso de pellejo contaminado" +msgstr[1] "bolsos de pellejo contaminado" +msgstr[2] "bolsos de pellejo contaminado" #. ~ Description for {'str': 'tainted hide bag'} #: data/json/items/armor/storage.json @@ -68420,9 +68661,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "H&K operational briefcase (empty)" msgid_plural "H&K operational briefcases (empty)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maletín operativo H&K (vacío)" +msgstr[1] "maletines operativos H&K (vacíos)" +msgstr[2] "maletines operativos H&K (vacíos)" #. ~ Description for {'str': 'H&K operational briefcase (empty)', 'str_pl': #. 'H&K operational briefcases (empty)'} @@ -68549,9 +68790,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "petpack" msgid_plural "petpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochila para perro" +msgstr[1] "mochilas para perro" +msgstr[2] "mochilas para perro" #. ~ Description for {'str': 'petpack'} #: data/json/items/armor/storage.json @@ -68789,9 +69030,9 @@ msgstr "" #: data/json/items/armor/storage.json msgid "travelpack" msgid_plural "travelpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolso de viaje" +msgstr[1] "bolsos de viaje" +msgstr[2] "bolsos de viaje" #. ~ Description for {'str': 'travelpack'} #: data/json/items/armor/storage.json @@ -68896,9 +69137,9 @@ msgstr "" #: data/json/items/armor/suits_clothes.json msgid "Hub 01 jumpsuit" msgid_plural "Hub 01 jumpsuits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mameluco Hub 01" +msgstr[1] "mamelucos Hub 01" +msgstr[2] "mamelucos Hub 01" #. ~ Description for {'str': 'Hub 01 jumpsuit'} #: data/json/items/armor/suits_clothes.json @@ -68977,9 +69218,9 @@ msgstr "" #: data/json/items/armor/suits_clothes.json msgid "zentai" msgid_plural "zentais" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zentai" +msgstr[1] "zentais" +msgstr[2] "zentais" #. ~ Description for {'str': 'zentai'} #: data/json/items/armor/suits_clothes.json @@ -69483,9 +69724,9 @@ msgstr "" #: data/json/items/armor/suits_protection.json msgid "Hub 01 environmental suit" msgid_plural "Hub 01 environmental suits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "traje ambiental Hub 01" +msgstr[1] "trajes ambientales Hub 01" +msgstr[2] "trajes ambientales Hub 01" #. ~ Description for {'str': 'Hub 01 environmental suit'} #: data/json/items/armor/suits_protection.json @@ -69623,9 +69864,9 @@ msgstr "" #: data/json/items/armor/suits_protection.json msgid "XL heavy survivor suit" msgid_plural "XL heavy survivor suits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "traje XL pesado de supervivencia" +msgstr[1] "trajes XL pesados de supervivencia" +msgstr[2] "trajes XL pesados de supervivencia" #. ~ Description for {'str': 'XL heavy survivor suit'} #: data/json/items/armor/suits_protection.json @@ -69839,9 +70080,9 @@ msgstr "Un antiguao peto griego, hecho de bronce." #: data/json/items/armor/torso_armor.json msgid "lamellar cuirass" msgid_plural "lamellar cuirasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "coraza lamelar" +msgstr[1] "corazas lamelar" +msgstr[2] "corazas lamelar" #. ~ Description for {'str': 'lamellar cuirass', 'str_pl': 'lamellar #. cuirasses'} @@ -69904,9 +70145,9 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "hard chest guard" msgid_plural "hard chest guards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "protección dura para pecho" +msgstr[1] "protecciones duras para pecho" +msgstr[2] "protecciones duras para pecho" #. ~ Description for {'str': 'hard chest guard'} #: data/json/items/armor/torso_armor.json @@ -69935,9 +70176,9 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "scrap cuirass" msgid_plural "scrap cuirasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "coraza de chatarra" +msgstr[1] "corazas de chatarra" +msgstr[2] "corazas de chatarra" #. ~ Description for {'str': 'scrap cuirass', 'str_pl': 'scrap cuirasses'} #: data/json/items/armor/torso_armor.json @@ -69984,9 +70225,9 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "occult bone armor" msgid_plural "occult bone armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura mística de hueso" +msgstr[1] "armaduras místicas de hueso" +msgstr[2] "armaduras místicas de hueso" #. ~ Description for {'str': 'occult bone armor'} #: data/json/items/armor/torso_armor.json @@ -70002,9 +70243,9 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "lamé (foil)" msgid_plural "lamés (foil)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lamé (florete)" +msgstr[1] "lamé (floretes)" +msgstr[2] "lamé (floretes)" #. ~ Description for {'str': 'lamé (foil)', 'str_pl': 'lamés (foil)'} #: data/json/items/armor/torso_armor.json @@ -70020,9 +70261,9 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "lamé (saber)" msgid_plural "lamés (saber)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lamé (sable)" +msgstr[1] "lamé (sables)" +msgstr[2] "lamé (sables)" #. ~ Description for {'str': 'lamé (saber)', 'str_pl': 'lamés (saber)'} #: data/json/items/armor/torso_armor.json @@ -70097,9 +70338,9 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "underarm protector" msgid_plural "underarm protectors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "protector de axila" +msgstr[1] "protectores de axila" +msgstr[2] "protectores de axila" #. ~ Description for {'str': 'underarm protector'} #: data/json/items/armor/torso_armor.json @@ -70113,9 +70354,9 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "plastic chest protector" msgid_plural "plastic chest protectors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "protector plástico de torso" +msgstr[1] "protectores plásticos de torso" +msgstr[2] "protectores plásticos de torso" #. ~ Description for {'str': 'plastic chest protector'} #: data/json/items/armor/torso_armor.json @@ -70397,9 +70638,9 @@ msgstr "" #: data/json/items/armor/torso_clothes.json msgid "leotard" msgid_plural "leotard" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leotardo" +msgstr[1] "leotardo" +msgstr[2] "leotardo" #. ~ Description for {'str_sp': 'leotard'} #: data/json/items/armor/torso_clothes.json @@ -70655,9 +70896,9 @@ msgstr "" #: data/json/items/armor/torso_clothes.json msgid "tour t-shirt" msgid_plural "tour t-shirts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "remera rockera" +msgstr[1] "remeras rockeras" +msgstr[2] "remeras rockeras" #: data/json/items/armor/torso_clothes.json msgid "" @@ -71080,9 +71321,9 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "sleeveless underwear top" msgid_plural "sleeveless underwear tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "camiseta sin mangas" +msgstr[1] "camisetas sin mangas" +msgstr[2] "camisetas sin mangas" #. ~ Description for {'str': 'sleeveless underwear top'} #: data/json/items/armor/undergarment.json @@ -71109,9 +71350,9 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "thermal shirt" msgid_plural "thermal shirts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "remera térmica" +msgstr[1] "remeras térmicas" +msgstr[2] "remeras térmicas" #. ~ Description for {'str': 'thermal shirt'} #: data/json/items/armor/undergarment.json @@ -71217,9 +71458,9 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "unitard" msgid_plural "unitards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "unitard" +msgstr[1] "unitards" +msgstr[2] "unitards" #. ~ Description for {'str': 'unitard'} #: data/json/items/armor/undergarment.json @@ -71235,9 +71476,9 @@ msgstr "" #: data/json/items/book/archery.json msgid "Lessons for the Novice Bowhunter" msgid_plural "copies of Lessons for the Novice Bowhunter" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Lecciones para el Cazador con Arco Principiante" +msgstr[1] "copias de Lecciones para el Cazador con Arco Principiante" +msgstr[2] "copias de Lecciones para el Cazador con Arco Principiante" #. ~ Description for {'str': 'Lessons for the Novice Bowhunter', 'str_pl': #. 'copies of Lessons for the Novice Bowhunter'} @@ -71253,9 +71494,9 @@ msgstr "" #: data/json/items/book/archery.json msgid "Archery for Kids" msgid_plural "issues of Archery for Kids" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Arquería para Niños" +msgstr[1] "fascículos de Arquería para Niños" +msgstr[2] "fascículos de Arquería para Niños" #. ~ Description for {'str': 'Archery for Kids', 'str_pl': 'issues of Archery #. for Kids'} @@ -71271,9 +71512,9 @@ msgstr "" #: data/json/items/book/archery.json msgid "Zen and the Art of Archery" msgid_plural "copies of Zen and the Art of Archery" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Zen y el Arte de la Arquería" +msgstr[1] "copias de El Zen y el Arte de la Arquería" +msgstr[2] "copias de El Zen y el Arte de la Arquería" #. ~ Description for {'str': 'Zen and the Art of Archery', 'str_pl': 'copies #. of Zen and the Art of Archery'} @@ -71304,9 +71545,9 @@ msgstr "" #: data/json/items/book/barter.json msgid "How to Succeed in Business" msgid_plural "copies of How to Succeed in Business" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cómo tener Éxito en los Negocios" +msgstr[1] "copias de Cómo tener Éxito en los Negocios" +msgstr[2] "copias de Cómo tener Éxito en los Negocios" #. ~ Description for {'str': 'How to Succeed in Business', 'str_pl': 'copies #. of How to Succeed in Business'} @@ -71317,9 +71558,9 @@ msgstr "Es útil si quieres obtener un buen negocio cuando compras cosas." #: data/json/items/book/barter.json msgid "Advanced Economics" msgid_plural "copies of Advanced Economics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Economía Avanzada" +msgstr[1] "copias de Economía Avanzada" +msgstr[2] "copias de Economía Avanzada" #. ~ Description for {'str': 'Advanced Economics', 'str_pl': 'copies of #. Advanced Economics'} @@ -71330,9 +71571,9 @@ msgstr "Un texto escolar sobre economía." #: data/json/items/book/bashing.json msgid "Batter Up!" msgid_plural "issues of Batter Up!" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "¡Al Bate!" +msgstr[1] "fascículos de ¡Al Bate!" +msgstr[2] "fascículos de ¡Al Bate!" #. ~ Description for {'str': 'Batter Up!', 'str_pl': 'issues of Batter Up!'} #: data/json/items/book/bashing.json @@ -71366,9 +71607,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Mycenacean Hymns" msgid_plural "copies of Mycenacean Hymns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Hymnos Myceanos" +msgstr[1] "copias de Hymnos Myceanos" +msgstr[2] "copias de Hymnos Myceanos" #. ~ Description for {'str': 'Mycenacean Hymns', 'str_pl': 'copies of #. Mycenacean Hymns'} @@ -71384,9 +71625,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Eastern Orthodox Bible" msgid_plural "copies of Eastern Orthodox Bible" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Biblia Ortodoxa de Oriente" +msgstr[1] "copias de Biblia Ortodoxa de Oriente" +msgstr[2] "copias de Biblia Ortodoxa de Oriente" #. ~ Description for {'str': 'Eastern Orthodox Bible', 'str_pl': 'copies of #. Eastern Orthodox Bible'} @@ -71398,9 +71639,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Gideon Bible" msgid_plural "copies of Gideon Bible" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Biblia de Gedeón" +msgstr[1] "copias de Biblia de Gedeón" +msgstr[2] "copias de Biblia de Gedeón" #. ~ Description for {'str': 'Gideon Bible', 'str_pl': 'copies of Gideon #. Bible'} @@ -71428,9 +71669,9 @@ msgstr "Una copia de un solo volumen del texto religioso central del Sijismo." #: data/json/items/book/bloat.json msgid "Hadith" msgid_plural "copies of Hadith" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Hadiz" +msgstr[1] "copias de Hadiz" +msgstr[2] "copias de Hadiz" #. ~ Description for {'str': 'Hadith', 'str_pl': 'copies of Hadith'} #: data/json/items/book/bloat.json @@ -71517,9 +71758,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Quran" msgid_plural "copies of Quran" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Corán" +msgstr[1] "copias de Corán" +msgstr[2] "copias de Corán" #. ~ Description for {'str': 'Quran', 'str_pl': 'copies of Quran'} #: data/json/items/book/bloat.json @@ -71583,9 +71824,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Talmud" msgid_plural "copies of Talmud" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Talmud" +msgstr[1] "copias de Talmud" +msgstr[2] "copias de Talmud" #. ~ Description for {'str': 'Talmud', 'str_pl': 'copies of Talmud'} #: data/json/items/book/bloat.json @@ -71600,9 +71841,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Tanakh" msgid_plural "copies of Tanakh" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Tanaj" +msgstr[1] "copias de Tanaj" +msgstr[2] "copias de Tanaj" #. ~ Description for {'str': 'Tanakh', 'str_pl': 'copies of Tanakh'} #: data/json/items/book/bloat.json @@ -71615,9 +71856,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "The Tripitaka" msgid_plural "copies of The Tripitaka" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Tripitaka" +msgstr[1] "copias de El Tripitaka" +msgstr[2] "copias de El Tripitaka" #. ~ Description for {'str': 'The Tripitaka', 'str_pl': 'copies of The #. Tripitaka'} @@ -71666,9 +71907,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "The Satanic Bible" msgid_plural "copies of The Satanic Bible" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "La Biblia Satánica" +msgstr[1] "copias de La Biblia Satánica" +msgstr[2] "copias de La Biblia Satánica" #. ~ Description for {'str': 'The Satanic Bible', 'str_pl': 'copies of The #. Satanic Bible'} @@ -71701,9 +71942,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "priest's diary" msgid_plural "priests' diaries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "diario de cura" +msgstr[1] "diarios de cura" +msgstr[2] "diarios de cura" #. ~ Description for {'str': "priest's diary", 'str_pl': "priests' diaries"} #: data/json/items/book/bloat.json @@ -71713,9 +71954,9 @@ msgstr "Un librito lleno con entradas diarias en latín." #: data/json/items/book/bloat.json msgid "The Hitchhiker's Guide to the Cataclysm" msgid_plural "copies of The Hitchhiker's Guide to the Cataclysm" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía del Autoestopista Cataclísmico" +msgstr[1] "copias de Guía del Autoestopista Cataclísmico" +msgstr[2] "copias de Guía del Autoestopista Cataclísmico" #. ~ Description for {'str': "The Hitchhiker's Guide to the Cataclysm", #. 'str_pl': "copies of The Hitchhiker's Guide to the Cataclysm"} @@ -71730,9 +71971,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Murdered by the Grapevine" msgid_plural "copies of Murdered by the Grapevine" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Asesinado por la Vid" +msgstr[1] "copias de Asesinado por la Vid" +msgstr[2] "copias de Asesinado por la Vid" #. ~ Description for {'str': 'Murdered by the Grapevine', 'str_pl': 'copies of #. Murdered by the Grapevine'} @@ -71751,9 +71992,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Come Fly the Treacherous Skies" msgid_plural "copies of Come Fly the Treacherous Skies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Vení a Volar por los Cielos Traidores" +msgstr[1] "copias de Vení a Volar por los Cielos Traidores" +msgstr[2] "copias de Vení a Volar por los Cielos Traidores" #. ~ Description for {'str': 'Come Fly the Treacherous Skies', 'str_pl': #. 'copies of Come Fly the Treacherous Skies'} @@ -71771,9 +72012,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Lies, Damn Lies, and Rocket Science" msgid_plural "copies of Lies, Damn Lies, and Rocket Science" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Mentiras, Malditas Mentiras y Ciencia Espacial" +msgstr[1] "copias de Mentiras, Malditas Mentiras y Ciencia Espacial" +msgstr[2] "copias de Mentiras, Malditas Mentiras y Ciencia Espacial" #. ~ Description for {'str': 'Lies, Damn Lies, and Rocket Science', 'str_pl': #. 'copies of Lies, Damn Lies, and Rocket Science'} @@ -71792,9 +72033,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Visions in Solitude" msgid_plural "copies of Visions in Solitude" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Revelaciones en Soledad" +msgstr[1] "copias de Revelaciones en Soledad" +msgstr[2] "copias de Revelaciones en Soledad" #. ~ Description for {'str': 'Visions in Solitude', 'str_pl': 'copies of #. Visions in Solitude'} @@ -71807,9 +72048,9 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Zombie Survival Guide" msgid_plural "copies of Zombie Survival Guide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Supervivencia ante Zombis" +msgstr[1] "copias de Guía de Supervivencia ante Zombis" +msgstr[2] "copias de Guía de Supervivencia ante Zombis" #. ~ Description for {'str': 'Zombie Survival Guide', 'str_pl': 'copies of #. Zombie Survival Guide'} @@ -71824,9 +72065,9 @@ msgstr "" #: data/json/items/book/computer.json msgid "SICP" msgid_plural "copies of SICP" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "SICP" +msgstr[1] "copias de SICP" +msgstr[2] "copias de SICP" #. ~ Description for {'str': 'SICP', 'str_pl': 'copies of SICP'} #: data/json/items/book/computer.json @@ -71841,9 +72082,9 @@ msgstr "" #: data/json/items/book/computer.json msgid "Computer Science 301" msgid_plural "copies of Computer Science 301" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Ciencias de la Computación 3" +msgstr[1] "copias de Ciencias de la Computación 3" +msgstr[2] "copias de Ciencias de la Computación 3" #. ~ Description for {'str': 'Computer Science 301', 'str_pl': 'copies of #. Computer Science 301'} @@ -71854,9 +72095,9 @@ msgstr "Un texto escolar sobre las ciencias de la computación." #: data/json/items/book/computer.json msgid "How to Browse the Web" msgid_plural "copies of How to Browse the Web" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cómo Navegar por la Web" +msgstr[1] "copias de Cómo Navegar por la Web" +msgstr[2] "copias de Cómo Navegar por la Web" #. ~ Description for {'str': 'How to Browse the Web', 'str_pl': 'copies of How #. to Browse the Web'} @@ -71867,9 +72108,9 @@ msgstr "Información sobre computadoras para principiantes." #: data/json/items/book/computer.json msgid "Computer World" msgid_plural "issues of Computer World" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Mundo Computadora" +msgstr[1] "fascículos de Mundo Computadora" +msgstr[2] "fascículos de Mundo Computadora" #. ~ Description for {'str': 'Computer World', 'str_pl': 'issues of Computer #. World'} @@ -71883,9 +72124,9 @@ msgstr "" #: data/json/items/book/computer.json msgid "Computer Science 101" msgid_plural "copies of Computer Science 101" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Ciencias de la Computación 1" +msgstr[1] "copias de Ciencias de la Computación 1" +msgstr[2] "copias de Ciencias de la Computación 1" #. ~ Description for {'str': 'Computer Science 101', 'str_pl': 'copies of #. Computer Science 101'} @@ -71896,9 +72137,9 @@ msgstr "Un libro de texto sobre computadoras de nivel básico." #: data/json/items/book/computer.json msgid "Principles of Advanced Programming" msgid_plural "copies of Principles of Advanced Programming" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Principios de Programación Avanzada" +msgstr[1] "copias de Principios de Programación Avanzada" +msgstr[2] "copias de Principios de Programación Avanzada" #. ~ Description for {'str': 'Principles of Advanced Programming', 'str_pl': #. 'copies of Principles of Advanced Programming'} @@ -71913,9 +72154,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Advanced Physical Chemistry" msgid_plural "copies of Advanced Physical Chemistry" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Físico-química Avanzada" +msgstr[1] "copias de Físico-química Avanzada" +msgstr[2] "copias de Físico-química Avanzada" #. ~ Description for {'str': 'Advanced Physical Chemistry', 'str_pl': 'copies #. of Advanced Physical Chemistry'} @@ -71930,9 +72171,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "The Homebrewer's Bible" msgid_plural "copies of The Homebrewer's Bible" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "La Biblia del Cervecero" +msgstr[1] "copias de La Biblia del Cervecero" +msgstr[2] "copias de La Biblia del Cervecero" #. ~ Description for {'str': "The Homebrewer's Bible", 'str_pl': "copies of #. The Homebrewer's Bible"} @@ -71948,9 +72189,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Cooking on a Budget" msgid_plural "copies of Cooking on a Budget" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cocinando con Poca Plata" +msgstr[1] "copias de Cocinando con Poca Plata" +msgstr[2] "copias de Cocinando con Poca Plata" #. ~ Description for {'str': 'Cooking on a Budget', 'str_pl': 'copies of #. Cooking on a Budget'} @@ -71964,9 +72205,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "To Serve Man" msgid_plural "copies of To Serve Man" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Servir al Hombre" +msgstr[1] "copias de Servir al Hombre" +msgstr[2] "copias de Servir al Hombre" #. ~ Description for {'str': 'To Serve Man', 'str_pl': 'copies of To Serve #. Man'} @@ -71977,9 +72218,9 @@ msgstr "Es... ¡un libro de recetas!" #: data/json/items/book/cooking.json msgid "Cucina Italiana" msgid_plural "copies of Cucina Italiana" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cucina Italiana" +msgstr[1] "copias de Cucina Italiana" +msgstr[2] "copias de Cucina Italiana" #. ~ Description for {'str': 'Cucina Italiana', 'str_pl': 'copies of Cucina #. Italiana'} @@ -72033,9 +72274,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Bon Appetit" msgid_plural "issues of Bon Appetit" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Bon Appetit" +msgstr[1] "fascículos de Bon Appetit" +msgstr[2] "fascículos de Bon Appetit" #. ~ Description for {'str': 'Bon Appetit', 'str_pl': 'issues of Bon Appetit'} #: data/json/items/book/cooking.json @@ -72048,9 +72289,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Glamopolitan" msgid_plural "issues of Glamopolitan" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Glamopolitan" +msgstr[1] "fascículos de Glamopolitan" +msgstr[2] "fascículos de Glamopolitan" #. ~ Description for {'str': 'Glamopolitan', 'str_pl': 'issues of #. Glamopolitan'} @@ -72084,9 +72325,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "PE050 \"Alpha\": Preliminary Report" msgid_plural "copies of PE050 \"Alpha\": Preliminary Report" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "PE050 \"Alpha\": Informe Preliminar" +msgstr[1] "copias de PE050 \"Alpha\": Informe Preliminar" +msgstr[2] "copias de PE050 \"Alpha\": Informe Preliminar" #. ~ Description for {'str': 'PE050 "Alpha": Preliminary Report', 'str_pl': #. 'copies of PE050 "Alpha": Preliminary Report'} @@ -72123,9 +72364,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "PE065 \"Chimera\": Best Practices" msgid_plural "copies of PE065 \"Chimera\": Best Practices" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "PE065 \"Chimera\": Mejores Prácticas" +msgstr[1] "copias de PE065 \"Chimera\": Mejores Prácticas" +msgstr[2] "copias de PE065 \"Chimera\": Mejores Prácticas" #. ~ Description for {'str': 'PE065 "Chimera": Best Practices', 'str_pl': #. 'copies of PE065 "Chimera": Best Practices'} @@ -72222,9 +72463,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "PE023 \"Medical\": Application and Findings" msgid_plural "copies of PE023 \"Medical\": Application and Findings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "PE023 \"Medicinal\": Aplicación y Descubrimientos" +msgstr[1] "copias de PE023 \"Medicinal\": Aplicación y Descubrimientos" +msgstr[2] "copias de PE023 \"Medicinal\": Aplicación y Descubrimientos" #. ~ Description for {'str': 'PE023 "Medical": Application and Findings', #. 'str_pl': 'copies of PE023 "Medical": Application and Findings'} @@ -72240,9 +72481,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "PE070 \"Raptor\": Proposal" msgid_plural "copies of PE070 \"Raptor\": Proposal" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "PE070 \"Raptor\": Propuesta" +msgstr[1] "copias de PE070 \"Raptor\": Propuesta" +msgstr[2] "copias de PE070 \"Raptor\": Propuesta" #. ~ Description for {'str': 'PE070 "Raptor": Proposal', 'str_pl': 'copies of #. PE070 "Raptor": Proposal'} @@ -72259,9 +72500,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Best Practices for Compound Delivery" msgid_plural "copies of Best Practices for Compound Delivery" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Mejores Maneras de Suministrar un Compuesto" +msgstr[1] "copias de Mejores Maneras de Suministrar un Compuesto" +msgstr[2] "copias de Mejores Maneras de Suministrar un Compuesto" #. ~ Description for {'str': 'Best Practices for Compound Delivery', 'str_pl': #. 'copies of Best Practices for Compound Delivery'} @@ -72282,9 +72523,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "CRC-Merck Handbook, 4th edition" msgid_plural "copies of CRC-Merck Handbook, 4th edition" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía CRC-Merck, 4ta edición" +msgstr[1] "copias de Guía CRC-Merck, 4ta edición" +msgstr[2] "copias de Guía CRC-Merck, 4ta edición" #. ~ Description for {'str': 'CRC-Merck Handbook, 4th edition', 'str_pl': #. 'copies of CRC-Merck Handbook, 4th edition'} @@ -72339,9 +72580,9 @@ msgstr "Un libro escolar sobre química." #: data/json/items/book/cooking.json msgid "The Vinegar Maker's Handbook" msgid_plural "copies of Vinegar Maker's Handbook" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "La Guía para Hacer Vinagre" +msgstr[1] "copias de La Guía para Hacer Vinagre" +msgstr[2] "copias de La Guía para Hacer Vinagre" #. ~ Description for {'str': "The Vinegar Maker's Handbook", 'str_pl': "copies #. of Vinegar Maker's Handbook"} @@ -72358,9 +72599,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Drink the Harvest" msgid_plural "copies of Drink the Harvest" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Tomarse la Cosecha" +msgstr[1] "copias de Tomarse la Cosecha" +msgstr[2] "copias de Tomarse la Cosecha" #. ~ Description for {'str': 'Drink the Harvest', 'str_pl': 'copies of Drink #. the Harvest'} @@ -72375,9 +72616,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Offal Holiday Cooking" msgid_plural "copies of Offal Holiday Cooking" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cocinando Achuras para las Fiestas" +msgstr[1] "copias de Cocinando Achuras para las Fiestas" +msgstr[2] "copias de Cocinando Achuras para las Fiestas" #. ~ Description for {'str': 'Offal Holiday Cooking', 'str_pl': 'copies of #. Offal Holiday Cooking'} @@ -72393,9 +72634,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Things to do with Milk" msgid_plural "copies of Things to do with Milk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cosas para hacer con Leche" +msgstr[1] "copias de Cosas para hacer con Leche" +msgstr[2] "copias de Cosas para hacer con Leche" #. ~ Description for {'str': 'Things to do with Milk', 'str_pl': 'copies of #. Things to do with Milk'} @@ -72409,9 +72650,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Liver-Licious Recipes Your Kids Will Love" msgid_plural "copies of Liver-Licious Recipes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Recetas Higadísimas Que Tus Chicos Amarán" +msgstr[1] "copias de Recetas Higadísimas Que Tus Chicos Amarán" +msgstr[2] "copias de Recetas Higadísimas Que Tus Chicos Amarán" #. ~ Description for {'str': 'Liver-Licious Recipes Your Kids Will Love', #. 'str_pl': 'copies of Liver-Licious Recipes'} @@ -72428,9 +72669,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Dainty Dishes Fit for a King" msgid_plural "copies of Dainty Dishes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Platos Delicados" +msgstr[1] "copias de Platos Delicados" +msgstr[2] "copias de Platos Delicados" #. ~ Description for {'str': 'Dainty Dishes Fit for a King', 'str_pl': 'copies #. of Dainty Dishes'} @@ -72447,9 +72688,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Eat Your Way to a Fit Physique" msgid_plural "copies of Eat Your Way" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Comé a Tu Manera" +msgstr[1] "copias de Comé a Tu Manera" +msgstr[2] "copias de Comé a Tu Manera" #. ~ Description for {'str': 'Eat Your Way to a Fit Physique', 'str_pl': #. 'copies of Eat Your Way'} @@ -72464,9 +72705,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Food Fashions for Young Moderns" msgid_plural "copies of Food Fashions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Moda de Cocina" +msgstr[1] "copias de Moda de Cocina" +msgstr[2] "copias de Moda de Cocina" #. ~ Description for {'str': 'Food Fashions for Young Moderns', 'str_pl': #. 'copies of Food Fashions'} @@ -72485,9 +72726,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Winemaking for Beginners" msgid_plural "copies of Winemaking for Beginners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Enología para Principiantes" +msgstr[1] "copias de Enología para Principiantes" +msgstr[2] "copias de Enología para Principiantes" #. ~ Description for {'str': 'Winemaking for Beginners', 'str_pl': 'copies of #. Winemaking for Beginners'} @@ -72502,9 +72743,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "You Can Can at Home" msgid_plural "copies of You Can Can at Home" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Podés Enlatar en Casa" +msgstr[1] "copias de Podés Enlatar en Casa" +msgstr[2] "copias de Podés Enlatar en Casa" #. ~ Description for {'str': 'You Can Can at Home', 'str_pl': 'copies of You #. Can Can at Home'} @@ -72521,9 +72762,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Can Sealer Instructions" msgid_plural "copies of Can Sealer Instructions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Instrucciones para Sellar Latas" +msgstr[1] "copias de Instrucciones para Sellar Latas" +msgstr[2] "copias de Instrucciones para Sellar Latas" #. ~ Description for {'str': 'Can Sealer Instructions', 'str_pl': 'copies of #. Can Sealer Instructions'} @@ -72540,9 +72781,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "The Baker's Companion" msgid_plural "copies of The Baker's Companion" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Compañero del Panadero" +msgstr[1] "copias de El Compañero del Panadero" +msgstr[2] "copias de El Compañero del Panadero" #. ~ Description for {'str': "The Baker's Companion", 'str_pl': "copies of The #. Baker's Companion"} @@ -72556,9 +72797,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Fermenting Culture" msgid_plural "copies of Fermenting Culture" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cultura de la Fermentación" +msgstr[1] "copias de Cultura de la Fermentación" +msgstr[2] "copias de Cultura de la Fermentación" #. ~ Description for {'str': 'Fermenting Culture', 'str_pl': 'copies of #. Fermenting Culture'} @@ -72575,9 +72816,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Out of the Holler and into the Home: A guide to home distilation. " msgid_plural "copies of Out of the Holler" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Desde el Holler y al Hogar: Guía de Destilación Hogareña" +msgstr[1] "copias de Desde el Holler" +msgstr[2] "copias de Desde el Holler" #. ~ Description for {'str': 'Out of the Holler and into the Home: A guide to #. home distilation. ', 'str_pl': 'copies of Out of the Holler'} @@ -72592,9 +72833,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Sweets for your Sweet Child" msgid_plural "copies of Sweets for Sweet" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Golosinas para Golosos" +msgstr[1] "copias de Golosinas para Golosos" +msgstr[2] "copias de Golosinas para Golosos" #. ~ Description for {'str': 'Sweets for your Sweet Child', 'str_pl': 'copies #. of Sweets for Sweet'} @@ -72612,9 +72853,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Pocket Survival Cookbook" msgid_plural "copies of Pocket Survival Cookbook" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Bolsillo de Cocina de Supervivencia" +msgstr[1] "copias de Guía de Bolsillo de Cocina de Supervivencia" +msgstr[2] "copias de Guía de Bolsillo de Cocina de Supervivencia" #. ~ Description for {'str': 'Pocket Survival Cookbook', 'str_pl': 'copies of #. Pocket Survival Cookbook'} @@ -72627,9 +72868,9 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Tasting India" msgid_plural "copies of Tasting India" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Sabores de India" +msgstr[1] "copias de Sabores de India" +msgstr[2] "copias de Sabores de India" #. ~ Description for {'str': 'Tasting India', 'str_pl': 'copies of Tasting #. India'} @@ -72644,9 +72885,9 @@ msgstr "" #: data/json/items/book/cutting.json msgid "All About Swords" msgid_plural "issues of All About Swords" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Todo Sobre Espadas" +msgstr[1] "fascículos de Todo Sobre Espadas" +msgstr[2] "fascículos de Todo Sobre Espadas" #. ~ Description for {'str': 'All About Swords', 'str_pl': 'issues of All #. About Swords'} @@ -72679,9 +72920,9 @@ msgstr "" #: data/json/items/book/cutting.json msgid "Spetsnaz Knife Techniques" msgid_plural "copies of Spetsnaz Knife Techniques" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Técnicas Spetsnaz para Cuchillo" +msgstr[1] "copias de Técnicas Spetsnaz para Cuchillo" +msgstr[2] "copias de Técnicas Spetsnaz para Cuchillo" #. ~ Description for {'str': 'Spetsnaz Knife Techniques', 'str_pl': 'copies of #. Spetsnaz Knife Techniques'} @@ -72692,9 +72933,9 @@ msgstr "Un texto clásico soviético sobre el arte de atacar con una cuchilla." #: data/json/items/book/dodge.json msgid "Dance Dance Dance!" msgid_plural "issues of Dance Dance Dance!" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "¡Baila Baila Baila!" +msgstr[1] "copias de ¡Baila Baila Baila!" +msgstr[2] "copias de ¡Baila Baila Baila!" #. ~ Description for {'str': 'Dance Dance Dance!', 'str_pl': 'issues of Dance #. Dance Dance!'} @@ -72705,9 +72946,9 @@ msgstr "Aprendé los movimientos de los bailes de moda." #: data/json/items/book/dodge.json msgid "The Book of Dances" msgid_plural "copies of The Book of Dances" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Libro de las Danzas" +msgstr[1] "copias de El Libro de las Danzas" +msgstr[2] "copias de El Libro de las Danzas" #. ~ Description for {'str': 'The Book of Dances', 'str_pl': 'copies of The #. Book of Dances'} @@ -72724,9 +72965,9 @@ msgstr "" #: data/json/items/book/dodge.json msgid "Break a Leg!" msgid_plural "copies of Break a Leg!" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "¡Mucha mierda!" +msgstr[1] "copias de ¡Mucha mierda!" +msgstr[2] "copias de ¡Mucha mierda!" #. ~ Description for {'str': 'Break a Leg!', 'str_pl': 'copies of Break a #. Leg!'} @@ -72737,9 +72978,9 @@ msgstr "Es la Guía de Actuación y Arte Teatral para Niños." #: data/json/items/book/driving.json msgid "AAA Guide" msgid_plural "copies of AAA Guide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía AAA" +msgstr[1] "copias de Guía AAA" +msgstr[2] "copias de Guía AAA" #. ~ Description for {'str': 'AAA Guide', 'str_pl': 'copies of AAA Guide'} #: data/json/items/book/driving.json @@ -72768,9 +73009,9 @@ msgstr "Muchos artículos sobre coches y técnicas de conducción." #: data/json/items/book/driving.json msgid "The Rules of the Road" msgid_plural "copies of The Rules of the Road" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Reglas de Conducción" +msgstr[1] "copias de Reglas de Conducción" +msgstr[2] "copias de Reglas de Conducción" #. ~ Description for {'str': 'The Rules of the Road', 'str_pl': 'copies of The #. Rules of the Road'} @@ -72798,9 +73039,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "Advanced Electronics" msgid_plural "copies of Advanced Electronics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Electrónica Avanzada" +msgstr[1] "copias de Electrónica Avanzada" +msgstr[2] "copias de Electrónica Avanzada" #. ~ Description for {'str': 'Advanced Electronics', 'str_pl': 'copies of #. Advanced Electronics'} @@ -72811,9 +73052,9 @@ msgstr "Un texto escolar sobre diseño de circuitos." #: data/json/items/book/electronics.json msgid "Ham Radio Illustrated" msgid_plural "issues of Ham Radio Illustrated" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Radio-aficionado Ilustrado" +msgstr[1] "fascículos de Radio-aficionado Ilustrado" +msgstr[2] "fascículos de Radio-aficionado Ilustrado" #. ~ Description for {'str': 'Ham Radio Illustrated', 'str_pl': 'issues of Ham #. Radio Illustrated'} @@ -72829,9 +73070,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "What's a Transistor?" msgid_plural "copies of What's a Transistor?" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "¿Qué es un Transistor?" +msgstr[1] "copias de ¿Qué es un Transistor?" +msgstr[2] "copias de ¿Qué es un Transistor?" #. ~ Description for {'str': "What's a Transistor?", 'str_pl': "copies of #. What's a Transistor?"} @@ -72842,9 +73083,9 @@ msgstr "Un manual básico sobre electrónica y diseño de circuitos." #: data/json/items/book/electronics.json msgid "Amateur Home Radio for Enthusiasts" msgid_plural "copies of Amateur Home Radio for Enthusiasts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Radio Amateur para Entusiastas" +msgstr[1] "copias de Radio Amateur para Entusiastas" +msgstr[2] "copias de Radio Amateur para Entusiastas" #. ~ Description for {'str': 'Amateur Home Radio for Enthusiasts', 'str_pl': #. 'copies of Amateur Home Radio for Enthusiasts'} @@ -72877,9 +73118,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "Augmentative Tech Review" msgid_plural "issues of Augmentative Tech Review" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Reseña de Mejoramiento Técnico" +msgstr[1] "fascículos de Reseña de Mejoramiento Técnico" +msgstr[2] "fascículos de Reseña de Mejoramiento Técnico" #. ~ Description for {'str': 'Augmentative Tech Review', 'str_pl': 'issues of #. Augmentative Tech Review'} @@ -72954,9 +73195,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "Electronic Circuit Theory" msgid_plural "copies of Electronic Circuit Theory" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Teoría del Circuito Electrónico" +msgstr[1] "copias de Teoría del Circuito Electrónico" +msgstr[2] "copias de Teoría del Circuito Electrónico" #. ~ Description for {'str': 'Electronic Circuit Theory', 'str_pl': 'copies of #. Electronic Circuit Theory'} @@ -72970,9 +73211,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "Robots for Fun & Profit" msgid_plural "copies of Robots for Fun & Profit" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Robots para Diversión y Beneficio" +msgstr[1] "copias de Robots para Diversión y Beneficio" +msgstr[2] "copias de Robots para Diversión y Beneficio" #. ~ Description for {'str': 'Robots for Fun & Profit', 'str_pl': 'copies of #. Robots for Fun & Profit'} @@ -72985,16 +73226,16 @@ msgstr "Un libro raro sobre diseño de robots, con muchas guías paso a paso." #: data/json/items/book/electronics.json msgid "schematics" msgid_plural "schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema" +msgstr[1] "esquemas" +msgstr[2] "esquemas" #: data/json/items/book/electronics.json msgid "nurse bot schematics" msgid_plural "nurse bot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de enfermerobot" +msgstr[1] "esquemas de enfermerobot" +msgstr[2] "esquemas de enfermerobot" #. ~ Description for {'str_sp': 'nurse bot schematics'} #: data/json/items/book/electronics.json @@ -73012,9 +73253,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "grocery bot schematics" msgid_plural "grocery bot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de reposibot" +msgstr[1] "esquemas de reposibot" +msgstr[2] "esquemas de reposibot" #. ~ Description for {'str_sp': 'grocery bot schematics'} #: data/json/items/book/electronics.json @@ -73031,9 +73272,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "police bot schematics" msgid_plural "police bot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de policíabot" +msgstr[1] "esquemas de policíabot" +msgstr[2] "esquemas de policíabot" #. ~ Description for {'str_sp': 'police bot schematics'} #: data/json/items/book/electronics.json @@ -73049,9 +73290,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "eyebot schematics" msgid_plural "eyebot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de ojobot" +msgstr[1] "esquemas de ojobot" +msgstr[2] "esquemas de ojobot" #. ~ Description for {'str_sp': 'eyebot schematics'} #: data/json/items/book/electronics.json @@ -73067,9 +73308,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "security bot schematics" msgid_plural "security bot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de robot de seguridad" +msgstr[1] "esquemas de robot de seguridad" +msgstr[2] "esquemas de robot de seguridad" #. ~ Description for {'str_sp': 'security bot schematics'} #: data/json/items/book/electronics.json @@ -73085,9 +73326,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "skitterbot schematics" msgid_plural "skitterbot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de arañabot" +msgstr[1] "esquemas de arañabot" +msgstr[2] "esquemas de arañabot" #. ~ Description for {'str_sp': 'skitterbot schematics'} #: data/json/items/book/electronics.json @@ -73103,9 +73344,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "cleaner bot schematics" msgid_plural "cleaner bot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de robot de limpieza" +msgstr[1] "esquemas de robot de limpieza" +msgstr[2] "esquemas de robot de limpieza" #. ~ Description for {'str_sp': 'cleaner bot schematics'} #: data/json/items/book/electronics.json @@ -73139,9 +73380,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "riot control bot schematics" msgid_plural "riot control bot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de antidisturbot" +msgstr[1] "esquemas de antidisturbot" +msgstr[2] "esquemas de antidisturbot" #. ~ Description for {'str_sp': 'riot control bot schematics'} #: data/json/items/book/electronics.json @@ -73157,9 +73398,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "lab defense bot schematics" msgid_plural "lab defense bot schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de robot defensor de laboratorio" +msgstr[1] "esquemas de robot defensor de laboratorio" +msgstr[2] "esquemas de robot defensor de laboratorio" #. ~ Description for {'str_sp': 'lab defense bot schematics'} #: data/json/items/book/electronics.json @@ -73176,9 +73417,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "dispatch schematics" msgid_plural "dispatch schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de desplegador" +msgstr[1] "esquemas de desplegador" +msgstr[2] "esquemas de desplegador" #. ~ Description for {'str_sp': 'dispatch schematics'} #: data/json/items/book/electronics.json @@ -73196,9 +73437,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "military dispatch schematics" msgid_plural "military dispatch schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de desplegador militar" +msgstr[1] "esquemas de desplegador militar" +msgstr[2] "esquemas de desplegador militar" #. ~ Description for {'str_sp': 'military dispatch schematics'} #: data/json/items/book/electronics.json @@ -73216,9 +73457,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "anti-materiel turret schematics" msgid_plural "anti-materiel turret schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de torreta anti-material" +msgstr[1] "esquemas de torreta anti-material" +msgstr[2] "esquemas de torreta anti-material" #. ~ Description for {'str_sp': 'anti-materiel turret schematics'} #: data/json/items/book/electronics.json @@ -73234,9 +73475,9 @@ msgstr "" #: data/json/items/book/electronics.json msgid "milspec searchlight schematics" msgid_plural "milspec searchlight schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de foco reflector milspec" +msgstr[1] "esquemas de foco reflector milspec" +msgstr[2] "esquemas de foco reflector milspec" #. ~ Description for {'str_sp': 'milspec searchlight schematics'} #: data/json/items/book/electronics.json @@ -73267,9 +73508,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Art of Glassblowing" msgid_plural "copies of The Art of Glassblowing" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Arte de Soplar Vidrio" +msgstr[1] "copias de El Arte de Soplar Vidrio" +msgstr[2] "copias de El Arte de Soplar Vidrio" #. ~ Description for {'str': 'The Art of Glassblowing', 'str_pl': 'copies of #. The Art of Glassblowing'} @@ -73284,9 +73525,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Antique Adornments" msgid_plural "copies of Antique Adornments" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Adornos Antiguos" +msgstr[1] "copias de Adornos Antiguos" +msgstr[2] "copias de Adornos Antiguos" #. ~ Description for {'str': 'Antique Adornments', 'str_pl': 'copies of #. Antique Adornments'} @@ -73301,9 +73542,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Crafty Crafter's Quarterly" msgid_plural "Crafty Crafter's Quarterlies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Artista Artesano Trimestral" +msgstr[1] "Artista Artesano Trimestrales" +msgstr[2] "Artista Artesano Trimestrales" #. ~ Description for {'str': "Crafty Crafter's Quarterly", 'str_pl': "Crafty #. Crafter's Quarterlies"} @@ -73318,9 +73559,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "101 Crafts for Beginners" msgid_plural "copies of 101 Crafts for Beginners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "101 Fabricaciones para Principiantes" +msgstr[1] "copias de 101 Fabricaciones para Principiantes" +msgstr[2] "copias de 101 Fabricaciones para Principiantes" #. ~ Description for {'str': '101 Crafts for Beginners', 'str_pl': 'copies of #. 101 Crafts for Beginners'} @@ -73335,9 +73576,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Fletcher's Friend" msgid_plural "copies of The Fletcher's Friend" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Amigo del Flechero" +msgstr[1] "copias de El Amigo del Flechero" +msgstr[2] "copias de El Amigo del Flechero" #. ~ Description for {'str': "The Fletcher's Friend", 'str_pl': "copies of The #. Fletcher's Friend"} @@ -73356,9 +73597,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Bowyer's Buddy" msgid_plural "copies of The Bowyer's Buddy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Compañero del Arquero" +msgstr[1] "copias de El Compañero del Arquero" +msgstr[2] "copias de El Compañero del Arquero" #. ~ Description for {'str': "The Bowyer's Buddy", 'str_pl': "copies of The #. Bowyer's Buddy"} @@ -73375,9 +73616,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Handloader's Helper" msgid_plural "copies of The Handloader's Helper" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Ayudante del Cargador a Mano" +msgstr[1] "copias de El Ayudante del Cargador a Mano" +msgstr[2] "copias de El Ayudante del Cargador a Mano" #. ~ Description for {'str': "The Handloader's Helper", 'str_pl': "copies of #. The Handloader's Helper"} @@ -73437,9 +73678,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Streetfighter's Sidekick" msgid_plural "copies of The Streetfighter's Sidekick" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Compañero del Luchador Callejero" +msgstr[1] "copias de El Compañero del Luchador Callejero" +msgstr[2] "copias de El Compañero del Luchador Callejero" #. ~ Description for {'str': "The Streetfighter's Sidekick", 'str_pl': "copies #. of The Streetfighter's Sidekick"} @@ -73458,9 +73699,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Art of Japanese Armormaking" msgid_plural "copies of The Art of Japanese Armormaking" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Arte Japonés de la Fabricación de Armaduras" +msgstr[1] "copias de El Arte Japonés de la Fabricación de Armaduras" +msgstr[2] "copias de El Arte Japonés de la Fabricación de Armaduras" #. ~ Description for {'str': 'The Art of Japanese Armormaking', 'str_pl': #. 'copies of The Art of Japanese Armormaking'} @@ -73475,9 +73716,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Arms and Armor of Imperial China" msgid_plural "copies of Arms and Armor of Imperial China" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Armas y Armaduras de la China Imperial" +msgstr[1] "copias de Armas y Armaduras de la China Imperial" +msgstr[2] "copias de Armas y Armaduras de la China Imperial" #. ~ Description for {'str': 'Arms and Armor of Imperial China', 'str_pl': #. 'copies of Arms and Armor of Imperial China'} @@ -73496,9 +73737,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Studies in Historic Armorsmithing" msgid_plural "copies of Studies in Historic Armorsmithing" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Estudios sobre Fabricación Histórica de Armaduras" +msgstr[1] "copias de Estudios sobre Fabricación Histórica de Armaduras" +msgstr[2] "copias de Estudios sobre Fabricación Histórica de Armaduras" #. ~ Description for {'str': 'Studies in Historic Armorsmithing', 'str_pl': #. 'copies of Studies in Historic Armorsmithing'} @@ -73513,9 +73754,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "DIY Compendium" msgid_plural "copies of DIY Compendium" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Compendio Hágalo Usted Mismo" +msgstr[1] "copias de Compendio Hágalo Usted Mismo" +msgstr[2] "copias de Compendio Hágalo Usted Mismo" #. ~ Description for {'str': 'DIY Compendium', 'str_pl': 'copies of DIY #. Compendium'} @@ -73530,9 +73771,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "A History of Firefighting" msgid_plural "copies of A History of Firefighting" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Una Historia de los Bomberos" +msgstr[1] "copias de Una Historia de los Bomberos" +msgstr[2] "copias de Una Historia de los Bomberos" #. ~ Description for {'str': 'A History of Firefighting', 'str_pl': 'copies of #. A History of Firefighting'} @@ -73549,9 +73790,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Art and Science of Chemical Warfare" msgid_plural "copies of Art and Science of Chemical Warfare" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Arte y Ciencia de las Armas Químicas" +msgstr[1] "copias de Arte y Ciencia de las Armas Químicas" +msgstr[2] "copias de Arte y Ciencia de las Armas Químicas" #. ~ Description for {'str': 'Art and Science of Chemical Warfare', 'str_pl': #. 'copies of Art and Science of Chemical Warfare'} @@ -73570,9 +73811,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Swords of the Samurai" msgid_plural "copies of The Swords of the Samurai" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Las Espadas del Samurai" +msgstr[1] "copias de Las Espadas del Samurai" +msgstr[2] "copias de Las Espadas del Samurai" #. ~ Description for {'str': 'The Swords of the Samurai', 'str_pl': 'copies of #. The Swords of the Samurai'} @@ -73589,9 +73830,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Historic Weaponsmith" msgid_plural "copies of The Historic Weaponsmith" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Fabricación Histórica de Armas" +msgstr[1] "copias de Fabricación Histórica de Armas" +msgstr[2] "copias de Fabricación Histórica de Armas" #. ~ Description for {'str': 'The Historic Weaponsmith', 'str_pl': 'copies of #. The Historic Weaponsmith'} @@ -73608,9 +73849,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Welding and Metallurgy" msgid_plural "copies of Welding and Metallurgy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Soldadura y Metalúrgica" +msgstr[1] "copias de Soldadura y Metalúrgica" +msgstr[2] "copias de Soldadura y Metalúrgica" #. ~ Description for {'str': 'Welding and Metallurgy', 'str_pl': 'copies of #. Welding and Metallurgy'} @@ -73625,9 +73866,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "101 Home Repairs" msgid_plural "copies of 101 Home Repairs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "101 Reparaciones Hogareñas" +msgstr[1] "copias de 101 Reparaciones Hogareñas" +msgstr[2] "copias de 101 Reparaciones Hogareñas" #. ~ Description for {'str': '101 Home Repairs', 'str_pl': 'copies of 101 Home #. Repairs'} @@ -73642,9 +73883,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Complete Home Repair Guide" msgid_plural "copies of The Complete Home Repair Guide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "La Guía Completa de Reparación Hogareña" +msgstr[1] "copias de La Guía Completa de Reparación Hogareña" +msgstr[2] "copias de La Guía Completa de Reparación Hogareña" #. ~ Description for {'str': 'The Complete Home Repair Guide', 'str_pl': #. 'copies of The Complete Home Repair Guide'} @@ -73673,9 +73914,9 @@ msgstr "Un periódico fascinante acerca de pajareras y cómo construirlas." #: data/json/items/book/fabrication.json msgid "Building for Beginners" msgid_plural "copies of Building for Beginners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Construcción para Principiantes" +msgstr[1] "copias de Construcción para Principiantes" +msgstr[2] "copias de Construcción para Principiantes" #. ~ Description for {'str': 'Building for Beginners', 'str_pl': 'copies of #. Building for Beginners'} @@ -73690,9 +73931,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Engineering 301" msgid_plural "copies of Engineering 301" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Ingeniería 3" +msgstr[1] "copias de Ingeniería 3" +msgstr[2] "copias de Ingeniería 3" #. ~ Description for {'str': 'Engineering 301', 'str_pl': 'copies of #. Engineering 301'} @@ -73703,9 +73944,9 @@ msgstr "Un libro de texto sobre ingeniería civil y construcción." #: data/json/items/book/fabrication.json msgid "Machinery's Handbook" msgid_plural "copies of Machinery's Handbook" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Maquinaria" +msgstr[1] "copias de Guía de Maquinaria" +msgstr[2] "copias de Guía de Maquinaria" #. ~ Description for {'str': "Machinery's Handbook", 'str_pl': "copies of #. Machinery's Handbook"} @@ -73743,9 +73984,9 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "Concrete Constructions" msgid_plural "copies of Concrete Constructions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Construcciones Concretas" +msgstr[1] "copias de Construcciones Concretas" +msgstr[2] "copias de Construcciones Concretas" #. ~ Description for {'str': 'Concrete Constructions', 'str_pl': 'copies of #. Concrete Constructions'} @@ -73760,9 +74001,9 @@ msgstr "" #: data/json/items/book/firstaid.json msgid "Guide to Advanced Emergency Care" msgid_plural "copies of Guide to Advanced Emergency Care" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Cuidado Médico Avanzado" +msgstr[1] "copias de Guía de Cuidado Médico Avanzado" +msgstr[2] "copias de Guía de Cuidado Médico Avanzado" #. ~ Description for {'str': 'Guide to Advanced Emergency Care', 'str_pl': #. 'copies of Guide to Advanced Emergency Care'} @@ -73777,9 +74018,9 @@ msgstr "" #: data/json/items/book/firstaid.json msgid "Paramedics" msgid_plural "issues of Paramedics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Paramédicos" +msgstr[1] "fascículos de Paramédicos" +msgstr[2] "fascículos de Paramédicos" #. ~ Description for {'str': 'Paramedics', 'str_pl': 'issues of Paramedics'} #: data/json/items/book/firstaid.json @@ -73789,9 +74030,9 @@ msgstr "Una revista educativa para los paramédicos." #: data/json/items/book/firstaid.json msgid "The Big Book of First Aid" msgid_plural "copies of The Big Book of First Aid" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Gran Libro de Primeros Auxilios" +msgstr[1] "copias de El Gran Libro de Primeros Auxilios" +msgstr[2] "copias de El Gran Libro de Primeros Auxilios" #. ~ Description for {'str': 'The Big Book of First Aid', 'str_pl': 'copies of #. The Big Book of First Aid'} @@ -73803,9 +74044,9 @@ msgstr "" #: data/json/items/book/firstaid.json msgid "Pocket Guide to First Aid" msgid_plural "copies of Pocket Guide to First Aid" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Bolsillo de Primeros Auxilios" +msgstr[1] "copias de Guía de Bolsillo de Primeros Auxilios" +msgstr[2] "copias de Guía de Bolsillo de Primeros Auxilios" #. ~ Description for {'str': 'Pocket Guide to First Aid', 'str_pl': 'copies of #. Pocket Guide to First Aid'} @@ -73822,9 +74063,9 @@ msgstr "" #: data/json/items/book/firstaid.json msgid "First Responder Handbook" msgid_plural "copies of First Responder Handbook" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Instructivo de Primera Respuesta" +msgstr[1] "copias de Instructivo de Primera Respuesta" +msgstr[2] "copias de Instructivo de Primera Respuesta" #. ~ Description for {'str': 'First Responder Handbook', 'str_pl': 'copies of #. First Responder Handbook'} @@ -73852,9 +74093,9 @@ msgstr "Es una guía ilustrada acerca de tu equipo de primeros auxilios." #: data/json/items/book/firstaid.json msgid "Physicians' Desk Reference" msgid_plural "copies of Physicians' Desk Reference" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Referencia de Escritorio para Médicos" +msgstr[1] "copias de Referencia de Escritorio para Médicos" +msgstr[2] "copias de Referencia de Escritorio para Médicos" #. ~ Description for {'str': "Physicians' Desk Reference", 'str_pl': "copies #. of Physicians' Desk Reference"} @@ -73879,9 +74120,9 @@ msgstr "" #: data/json/items/book/firstaid.json msgid "Merck Veterinary Manual" msgid_plural "copies of Merck Veterinary Manual" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Manual Merck Veterinaria" +msgstr[1] "copias de Manual Merck Veterinaria" +msgstr[2] "copias de Manual Merck Veterinaria" #. ~ Description for {'str': 'Merck Veterinary Manual', 'str_pl': 'copies of #. Merck Veterinary Manual'} @@ -73904,9 +74145,9 @@ msgstr "" #: data/json/items/book/gun.json msgid "Guns n Ammo" msgid_plural "issues of Guns n Ammo" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Armas y Munición" +msgstr[1] "fascículos de Armas y Munición" +msgstr[2] "fascículos de Armas y Munición" #. ~ Description for {'str': 'Guns n Ammo', 'str_pl': 'issues of Guns n Ammo'} #: data/json/items/book/gun.json @@ -73917,9 +74158,9 @@ msgstr "" #: data/json/items/book/gun.json msgid "The Gun Owner's Handbook" msgid_plural "copies of The Gun Owner's Handbook" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "La Guía del Dueño de Arma" +msgstr[1] "copias de La Guía del Dueño de Arma" +msgstr[2] "copias de La Guía del Dueño de Arma" #. ~ Description for {'str': "The Gun Owner's Handbook", 'str_pl': "copies of #. The Gun Owner's Handbook"} @@ -73934,9 +74175,9 @@ msgstr "" #: data/json/items/book/gun.json msgid "Pocket Guide to Firearm Safety" msgid_plural "copies of Pocket Guide to Firearm Safety" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Bolsillo de Seguridad de Armas de Fuego" +msgstr[1] "copias de Guía de Bolsillo de Seguridad de Armas de Fuego" +msgstr[2] "copias de Guía de Bolsillo de Seguridad de Armas de Fuego" #. ~ Description for {'str': 'Pocket Guide to Firearm Safety', 'str_pl': #. 'copies of Pocket Guide to Firearm Safety'} @@ -73990,9 +74231,9 @@ msgstr "" #: data/json/items/book/lockpick.json msgid "MIT Guide to Lock Picking" msgid_plural "copies of MIT Guide to Lock Picking" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía MIT de Ganzúas" +msgstr[1] "copias de Guía MIT de Ganzúas" +msgstr[2] "copias de Guía MIT de Ganzúas" #. ~ Description for {'str': 'MIT Guide to Lock Picking', 'str_pl': 'copies of #. MIT Guide to Lock Picking'} @@ -74007,9 +74248,9 @@ msgstr "" #: data/json/items/book/maps.json msgid "abstract map" msgid_plural "abstract maps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mapa abstracto" +msgstr[1] "mapas abstractos" +msgstr[2] "mapas abstractos" #: data/json/items/book/maps.json msgid "scientific operations map" @@ -74123,9 +74364,9 @@ msgstr "" #: data/json/items/book/maps.json msgid "trail guide" msgid_plural "trail guides" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guía de sendas" +msgstr[1] "guías de sendas" +msgstr[2] "guías de sendas" #. ~ Use action message for {'str': 'trail guide'}. #: data/json/items/book/maps.json @@ -74593,9 +74834,9 @@ msgstr "" #: data/json/items/book/mechanics.json msgid "Internal Combustion Fundamentals" msgid_plural "copies of Internal Combustion Fundamentals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Fundamentos de la Combustión Interna" +msgstr[1] "copias de Fundamentos de la Combustión Interna" +msgstr[2] "copias de Fundamentos de la Combustión Interna" #. ~ Description for {'str': 'Internal Combustion Fundamentals', 'str_pl': #. 'copies of Internal Combustion Fundamentals'} @@ -74610,9 +74851,9 @@ msgstr "" #: data/json/items/book/mechanics.json msgid "army improvised field repairs manual" msgid_plural "army improvised field repairs manuals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "manual de reparaciones improvisadas" +msgstr[1] "manuales de reparaciones improvisadas" +msgstr[2] "manuales de reparaciones improvisadas" #. ~ Description for {'str': 'army improvised field repairs manual'} #: data/json/items/book/mechanics.json @@ -74626,9 +74867,9 @@ msgstr "" #: data/json/items/book/mechanics.json msgid "Popular Mechanics" msgid_plural "issues of Popular Mechanics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Mecánica Popular" +msgstr[1] "fascículos de Mecánica Popular" +msgstr[2] "fascículos de Mecánica Popular" #. ~ Description for {'str': 'Popular Mechanics', 'str_pl': 'issues of Popular #. Mechanics'} @@ -74643,9 +74884,9 @@ msgstr "" #: data/json/items/book/mechanics.json msgid "Under the Hood" msgid_plural "copies of Under the Hood" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Debajo del Capó" +msgstr[1] "copias de Debajo del Capó" +msgstr[2] "copias de Debajo del Capó" #. ~ Description for {'str': 'Under the Hood', 'str_pl': 'copies of Under the #. Hood'} @@ -74677,9 +74918,9 @@ msgstr "" #: data/json/items/book/mechanics.json msgid "Biodiesel: Renewable Fuel Resource" msgid_plural "copies of Biodiesel: Renewable Fuel Resource" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Biodiésel: Fuente de Combustible Renovable" +msgstr[1] "copias de Biodiésel: Fuente de Combustible Renovable" +msgstr[2] "copias de Biodiésel: Fuente de Combustible Renovable" #. ~ Description for {'str': 'Biodiesel: Renewable Fuel Resource', 'str_pl': #. 'copies of Biodiesel: Renewable Fuel Resource'} @@ -74690,9 +74931,9 @@ msgstr "Es un manual para estudiantes acerca del biodiésel." #: data/json/items/book/mechanics.json msgid "Mechanical Mastery" msgid_plural "copies of Mechanical Mastery" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Maestría Mecánica" +msgstr[1] "copias de Maestría Mecánica" +msgstr[2] "copias de Maestría Mecánica" #. ~ Description for {'str': 'Mechanical Mastery', 'str_pl': 'copies of #. Mechanical Mastery'} @@ -74723,9 +74964,9 @@ msgstr "" #: data/json/items/book/melee.json msgid "Close Quarter Fighting Manual" msgid_plural "copies of Close Quarter Fighting Manual" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Manual de Lucha en Espacios Cerrados" +msgstr[1] "copias de Manual de Lucha en Espacios Cerrados" +msgstr[2] "copias de Manual de Lucha en Espacios Cerrados" #. ~ Description for {'str': 'Close Quarter Fighting Manual', 'str_pl': #. 'copies of Close Quarter Fighting Manual'} @@ -74740,9 +74981,9 @@ msgstr "" #: data/json/items/book/misc.json msgid "paperback abstract" msgid_plural "paperback abstracts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "reseña en rústica" +msgstr[1] "reseñas en rústica" +msgstr[2] "reseñas en rústica" #. ~ Description for {'str': 'paperback abstract'} #: data/json/items/book/misc.json @@ -74764,9 +75005,9 @@ msgstr "Un comic de superheroes." #: data/json/items/book/misc.json msgid "King James Bible" msgid_plural "copies of King James Bible" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Biblia del Rey Jacobo" +msgstr[1] "copias de Biblia del Rey Jacobo" +msgstr[2] "copias de Biblia del Rey Jacobo" #. ~ Description for {'str': 'King James Bible', 'str_pl': 'copies of King #. James Bible'} @@ -75057,9 +75298,9 @@ msgstr "" #: data/json/items/book/misc.json msgid "Computer Gaming" msgid_plural "issues of Computer Gaming" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Juegos de Computadora" +msgstr[1] "fascículos de Juegos de Computadora" +msgstr[2] "fascículos de Juegos de Computadora" #. ~ Description for {'str': 'Computer Gaming', 'str_pl': 'issues of Computer #. Gaming'} @@ -75087,9 +75328,9 @@ msgstr "" #: data/json/items/book/misc.json msgid "Playboy" msgid_plural "issues of Playboy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Playboy" +msgstr[1] "fascículos de Playboy" +msgstr[2] "fascículos de Playboy" #. ~ Description for {'str': 'Playboy', 'str_pl': 'issues of Playboy'} #: data/json/items/book/misc.json @@ -75128,9 +75369,9 @@ msgstr "" #: data/json/items/book/misc.json msgid "Rural Digest-Examiner" msgid_plural "issues of Rural Digest-Examiner" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Compendio de Examinadores Rurales" +msgstr[1] "fascículos de Compendio de Examinadores Rurales" +msgstr[2] "fascículos de Compendio de Examinadores Rurales" #. ~ Description for {'str': 'Rural Digest-Examiner', 'str_pl': 'issues of #. Rural Digest-Examiner'} @@ -76671,9 +76912,9 @@ msgstr "Es una copia de \"Pedro Simple\" de Frederick Marryat." #: data/json/items/book/misc.json msgid "collector's edition book" msgid_plural "collector's edition books" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "libro edición de colección" +msgstr[1] "libros edición de colección" +msgstr[2] "libros edición de colección" #. ~ Description for {'str': "collector's edition book"} #: data/json/items/book/misc.json @@ -76873,9 +77114,9 @@ msgstr "" #: data/json/items/book/pistol.json msgid "Tactical Handgun Digest" msgid_plural "issues of Tactical Handgun Digest" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Compendio de Pistolas Tácticas" +msgstr[1] "fascículos de Compendio de Pistolas Tácticas" +msgstr[2] "fascículos de Compendio de Pistolas Tácticas" #. ~ Description for {'str': 'Tactical Handgun Digest', 'str_pl': 'issues of #. Tactical Handgun Digest'} @@ -76908,9 +77149,9 @@ msgstr "" #: data/json/items/book/rifle.json msgid "Modern Rifleman" msgid_plural "issues of Modern Rifleman" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Rifleros Modernos" +msgstr[1] "fascículos de Rifleros Modernos" +msgstr[2] "fascículos de Rifleros Modernos" #. ~ Description for {'str': 'Modern Rifleman', 'str_pl': 'issues of Modern #. Rifleman'} @@ -76941,9 +77182,9 @@ msgstr "" #: data/json/items/book/shotgun.json msgid "Trap and Field" msgid_plural "issues of Trap and Field" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Trampa y Campo" +msgstr[1] "fascículos de Trampa y Campo" +msgstr[2] "fascículos de Trampa y Campo" #. ~ Description for {'str': 'Trap and Field', 'str_pl': 'issues of Trap and #. Field'} @@ -76958,9 +77199,9 @@ msgstr "" #: data/json/items/book/shotgun.json msgid "Shotguns: The Art and Science" msgid_plural "copies of Shotguns: The Art and Science" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Escopetas: el Arte y la Ciencia" +msgstr[1] "copias de Escopetas: el Arte y la Ciencia" +msgstr[2] "copias de Escopetas: el Arte y la Ciencia" #. ~ Description for {'str': 'Shotguns: The Art and Science', 'str_pl': #. 'copies of Shotguns: The Art and Science'} @@ -76975,9 +77216,9 @@ msgstr "" #: data/json/items/book/smg.json msgid "Submachine Gun Enthusiast" msgid_plural "issues of Submachine Gun Enthusiast" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Entusiastas de los Subfusiles" +msgstr[1] "fascículos de Entusiastas de los Subfusiles" +msgstr[2] "fascículos de Entusiastas de los Subfusiles" #. ~ Description for {'str': 'Submachine Gun Enthusiast', 'str_pl': 'issues of #. Submachine Gun Enthusiast'} @@ -76993,9 +77234,9 @@ msgstr "" #: data/json/items/book/smg.json msgid "The Submachine Gun Handbook" msgid_plural "copies of The Submachine Gun Handbook" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Instructivo sobre Fusiles" +msgstr[1] "copias de El Instructivo sobre Fusiles" +msgstr[2] "copias de El Instructivo sobre Fusiles" #. ~ Description for {'str': 'The Submachine Gun Handbook', 'str_pl': 'copies #. of The Submachine Gun Handbook'} @@ -77026,9 +77267,9 @@ msgstr "" #: data/json/items/book/speech.json msgid "Self-Esteem for Dummies" msgid_plural "copies of Self-Esteem for Dummies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Autoestima para Tontos" +msgstr[1] "copias de Autoestima para Tontos" +msgstr[2] "copias de Autoestima para Tontos" #. ~ Description for {'str': 'Self-Esteem for Dummies', 'str_pl': 'copies of #. Self-Esteem for Dummies'} @@ -77039,9 +77280,9 @@ msgstr "Lleno de consejos útiles para demostrar confianza en tus palabras." #: data/json/items/book/speech.json msgid "Principles of Effective Communication" msgid_plural "copies of Principles of Effective Communication" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Principios de Comunicaciones Efectivas" +msgstr[1] "copias de Principios de Comunicaciones Efectivas" +msgstr[2] "copias de Principios de Comunicaciones Efectivas" #. ~ Description for {'str': 'Principles of Effective Communication', #. 'str_pl': 'copies of Principles of Effective Communication'} @@ -77053,9 +77294,9 @@ msgstr "" #: data/json/items/book/speech.json msgid "Dungeon Master's Guide: 6th Edition" msgid_plural "copies of Dungeon Master's Guide: 6th Edition" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía del Dungeon Master: 6ta edición" +msgstr[1] "copias de Guía del Dungeon Master: 6ta edición" +msgstr[2] "copias de Guía del Dungeon Master: 6ta edición" #. ~ Description for {'str': "Dungeon Master's Guide: 6th Edition", 'str_pl': #. "copies of Dungeon Master's Guide: 6th Edition"} @@ -77123,9 +77364,9 @@ msgstr "" #: data/json/items/book/survival.json msgid "Through the Lens" msgid_plural "copies of Through the Lens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "A través de la Lente" +msgstr[1] "copias de A través de la Lente" +msgstr[2] "copias de A través de la Lente" #. ~ Description for {'str': 'Through the Lens', 'str_pl': 'copies of Through #. the Lens'} @@ -77162,9 +77403,9 @@ msgstr "" #: data/json/items/book/survival.json msgid "Outdoor Adventures" msgid_plural "issues of Outdoor Adventures" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Aventuras al Aire Libre" +msgstr[1] "fascículos de Aventuras al Aire Libre" +msgstr[2] "fascículos de Aventuras al Aire Libre" #. ~ Description for {'str': 'Outdoor Adventures', 'str_pl': 'issues of #. Outdoor Adventures'} @@ -77195,9 +77436,9 @@ msgstr "" #: data/json/items/book/survival.json msgid "Pocket Survival Guide" msgid_plural "copies of Pocket Survival Guide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Bolsillo de Supervivencia" +msgstr[1] "copias de Guía de Bolsillo de Supervivencia" +msgstr[2] "copias de Guía de Bolsillo de Supervivencia" #. ~ Description for {'str': 'Pocket Survival Guide', 'str_pl': 'copies of #. Pocket Survival Guide'} @@ -77214,9 +77455,9 @@ msgstr "" #: data/json/items/book/survival.json msgid "Autobiography of a Mountain Man" msgid_plural "copies of Autobiography of a Mountain Man" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Autobiografía de los Montañistas" +msgstr[1] "copias de Autobiografía de los Montañistas" +msgstr[2] "copias de Autobiografía de los Montañistas" #. ~ Description for {'str': 'Autobiography of a Mountain Man', 'str_pl': #. 'copies of Autobiography of a Mountain Man'} @@ -77233,9 +77474,9 @@ msgstr "" #: data/json/items/book/survival.json msgid "Outdoor Survival Guide" msgid_plural "copies of Outdoor Survival Guide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Supervivencia al Aire Libre" +msgstr[1] "copias de Guía de Supervivencia al Aire Libre" +msgstr[2] "copias de Guía de Supervivencia al Aire Libre" #. ~ Description for {'str': 'Outdoor Survival Guide', 'str_pl': 'copies of #. Outdoor Survival Guide'} @@ -77250,9 +77491,9 @@ msgstr "" #: data/json/items/book/survival.json msgid "Natural Remedies of New England" msgid_plural "copies of Natural Remedies of New England" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Remedios Naturales de New England" +msgstr[1] "copias de Remedios Naturales de New England" +msgstr[2] "copias de Remedios Naturales de New England" #. ~ Description for {'str': 'Natural Remedies of New England', 'str_pl': #. 'copies of Natural Remedies of New England'} @@ -77267,9 +77508,9 @@ msgstr "" #: data/json/items/book/swimming.json msgid "Swim Planet" msgid_plural "issues of Swim Planet" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Planeta Natación" +msgstr[1] "fascículos de Planeta Natación" +msgstr[2] "fascículos de Planeta Natación" #. ~ Description for {'str': 'Swim Planet', 'str_pl': 'issues of Swim Planet'} #: data/json/items/book/swimming.json @@ -77279,9 +77520,9 @@ msgstr "El recurso líder en el mundo sobre deportes acuáticos." #: data/json/items/book/swimming.json msgid "Water Survival Training Field Manual" msgid_plural "copies of Water Survival Training Field Manual" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Manual de Supervivencia en el Agua" +msgstr[1] "copias de Manual de Supervivencia en el Agua" +msgstr[2] "copias de Manual de Supervivencia en el Agua" #. ~ Description for {'str': 'Water Survival Training Field Manual', 'str_pl': #. 'copies of Water Survival Training Field Manual'} @@ -77350,9 +77591,9 @@ msgstr "" #: data/json/items/book/tailor.json msgid "Sew What? Clothing!" msgid_plural "copies of Sew What? Clothing!" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "¿Coser qué? ¡Ropa!" +msgstr[1] "copias de ¿Coser qué? ¡Ropa!" +msgstr[2] "copias de ¿Coser qué? ¡Ropa!" #. ~ Description for {'str': 'Sew What? Clothing!', 'str_pl': 'copies of Sew #. What? Clothing!'} @@ -77381,9 +77622,9 @@ msgstr "" #: data/json/items/book/tailor.json msgid "Traditional Japanese Kimono" msgid_plural "copies of Traditional Japanese Kimono" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Kimonos Tradicionales Japoneses" +msgstr[1] "copias de Kimonos Tradicionales Japoneses" +msgstr[2] "copias de Kimonos Tradicionales Japoneses" #. ~ Description for {'str': 'Traditional Japanese Kimono', 'str_pl': 'copies #. of Traditional Japanese Kimono'} @@ -77396,9 +77637,9 @@ msgstr "" #: data/json/items/book/tailor.json msgid "Friendly, Humane Fashion" msgid_plural "copies of Friendly, Humane Fashion" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Moda Humana, Amigable" +msgstr[1] "copias de Moda Humana, Amigable" +msgstr[2] "copias de Moda Humana, Amigable" #. ~ Description for {'str': 'Friendly, Humane Fashion', 'str_pl': 'copies of #. Friendly, Humane Fashion'} @@ -77417,9 +77658,9 @@ msgstr "" #: data/json/items/book/tailor.json msgid "Sewing Techniques for Designers" msgid_plural "copies of Sewing Techniques for Designers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Técnicas de Costura para Diseñadores" +msgstr[1] "copias de Técnicas de Costura para Diseñadores" +msgstr[2] "copias de Técnicas de Costura para Diseñadores" #. ~ Description for {'str': 'Sewing Techniques for Designers', 'str_pl': #. 'copies of Sewing Techniques for Designers'} @@ -77434,9 +77675,9 @@ msgstr "" #: data/json/items/book/throw.json msgid "Diskobolus" msgid_plural "issues of Diskobolus" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Diskobolos" +msgstr[1] "copias de Diskobolos" +msgstr[2] "copias de Diskobolos" #. ~ Description for {'str': 'Diskobolus', 'str_pl': 'issues of Diskobolus'} #: data/json/items/book/throw.json @@ -77448,9 +77689,9 @@ msgstr "" #: data/json/items/book/throw.json msgid "The Complete Guide to Pitching" msgid_plural "copies of The Complete Guide to Pitching" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía Completa para el Lanzador" +msgstr[1] "copias de Guía Completa para el Lanzador" +msgstr[2] "copias de Guía Completa para el Lanzador" #. ~ Description for {'str': 'The Complete Guide to Pitching', 'str_pl': #. 'copies of The Complete Guide to Pitching'} @@ -77466,9 +77707,9 @@ msgstr "" #: data/json/items/book/traps.json msgid "How to Trap Anything" msgid_plural "copies of How to Trap Anything" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cómo Atrapar Cualquier Cosa" +msgstr[1] "copias de Cómo Atrapar Cualquier Cosa" +msgstr[2] "copias de Cómo Atrapar Cualquier Cosa" #. ~ Description for {'str': 'How to Trap Anything', 'str_pl': 'copies of How #. to Trap Anything'} @@ -77482,9 +77723,9 @@ msgstr "" #: data/json/items/book/traps.json msgid "Trapper's Life" msgid_plural "issues of Trapper's Life" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Vida de Trampero" +msgstr[1] "copias de Vida de Trampero" +msgstr[2] "copias de Vida de Trampero" #. ~ Description for {'str': "Trapper's Life", 'str_pl': "issues of Trapper's #. Life"} @@ -77499,9 +77740,9 @@ msgstr "" #: data/json/items/book/traps.json msgid "The Modern Trapper" msgid_plural "copies of The Modern Trapper" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Trampero Moderno" +msgstr[1] "copias de El Trampero Moderno" +msgstr[2] "copias de El Trampero Moderno" #. ~ Description for {'str': 'The Modern Trapper', 'str_pl': 'copies of The #. Modern Trapper'} @@ -77514,9 +77755,9 @@ msgstr "" #: data/json/items/book/traps.json msgid "FM 20-32 Mine/Countermine Operations manual" msgid_plural "copies of FM 20-32 Mine/Countermine Operations manual" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Manual de Mina/Contramina FM 20-32" +msgstr[1] "copias de Manual de Mina/Contramina FM 20-32" +msgstr[2] "copias de Manual de Mina/Contramina FM 20-32" #. ~ Description for {'str': 'FM 20-32 Mine/Countermine Operations manual', #. 'str_pl': 'copies of FM 20-32 Mine/Countermine Operations manual'} @@ -77533,9 +77774,9 @@ msgstr "" #: data/json/items/book/traps.json msgid "The Compleat Trapper" msgid_plural "copies of The Compleat Trapper" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "El Trampero Total" +msgstr[1] "copias de El Trampero Total" +msgstr[2] "copias de El Trampero Total" #. ~ Description for {'//~': 'The spelling is intentionally archaic, as this #. form is commonly used in the titles of books.', 'str': 'The Compleat @@ -77586,9 +77827,9 @@ msgstr "" #: data/json/items/book/unarmed.json msgid "101 Wrestling Moves" msgid_plural "copies of 101 Wrestling Moves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "101 Movimientos de Lucha" +msgstr[1] "copias de 101 Movimientos de Lucha" +msgstr[2] "copias de 101 Movimientos de Lucha" #. ~ Description for {'str': '101 Wrestling Moves', 'str_pl': 'copies of 101 #. Wrestling Moves'} @@ -77604,9 +77845,9 @@ msgstr "" #: data/json/items/classes/book.json msgid "readable magazine" msgid_plural "readable magazines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "revista legible" +msgstr[1] "revistas legibles" +msgstr[2] "revistas legibles" #: data/json/items/classes/book.json msgid "martial art manual" @@ -77618,16 +77859,16 @@ msgstr[2] "" #: data/json/items/classes/comestible.json msgid "Spice" msgid_plural "Spices" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Condimento" +msgstr[1] "Condimentos" +msgstr[2] "Condimentos" #: data/json/items/classes/gun.json msgid "base gun" msgid_plural "base guns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arma básica" +msgstr[1] "armas básicas" +msgstr[2] "armas básicas" #: data/json/items/classes/gun.json msgid "base flamethrower" @@ -77677,9 +77918,9 @@ msgstr[2] "" #: data/json/items/classes/gun.json msgid "base pistol" msgid_plural "base pistols" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pistola básica" +msgstr[1] "pistolas básicas" +msgstr[2] "pistolas básicas" #: data/json/items/classes/gun.json data/json/items/classes/range.json #: data/json/items/gun/20x66mm.json data/json/items/gun/bio.json @@ -77749,9 +77990,9 @@ msgstr[2] "rifles de acción manual" #: data/json/items/classes/gun.json msgid "semi-automatic rifle" msgid_plural "semi-automatic rifles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle semi-automático" +msgstr[1] "rifles semi-automáticos" +msgstr[2] "rifles semi-automáticos" #: data/json/items/classes/gun.json msgid "fully automatic rifle" @@ -77829,9 +78070,9 @@ msgstr[2] "" #: data/json/items/classes/gun.json data/mods/Generic_Guns/firearms/shot.json msgid "pump action shotgun" msgid_plural "pump action shotguns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "escopeta de acción de bombeo" +msgstr[1] "escopetas de acción de bombeo" +msgstr[2] "escopetas de acción de bombeo" #: data/json/items/classes/gun.json data/json/items/gun/20x66mm.json #: data/mods/Magiclysm/items/enchanted_ranged.json @@ -77954,9 +78195,9 @@ msgstr "tirar" #: data/mods/No_Fungi/comestibles.json msgid "marloss wine" msgid_plural "marloss wine" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vino de marloss" +msgstr[1] "vino de marloss" +msgstr[2] "vino de marloss" #. ~ Description for {'str_sp': 'marloss wine'} #: data/json/items/comestibles/alcohol.json @@ -77966,9 +78207,9 @@ msgstr "Es un vino blanco viscoso, hecho con la fruta del marloss." #: data/json/items/comestibles/alcohol.json msgid "Riesling" msgid_plural "Riesling" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Riesling" +msgstr[1] "Riesling" +msgstr[2] "Riesling" #. ~ Description for {'str_sp': 'Riesling'} #: data/json/items/comestibles/alcohol.json @@ -77990,9 +78231,9 @@ msgstr "El vino más popular de Estados Unidos, y con razón." #: data/json/items/comestibles/alcohol.json msgid "Cabernet Sauvignon" msgid_plural "Cabernet Sauvignon" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cabernet Sauvignon" +msgstr[1] "Cabernet Sauvignon" +msgstr[2] "Cabernet Sauvignon" #. ~ Description for {'str_sp': 'Cabernet Sauvignon'} #: data/json/items/comestibles/alcohol.json @@ -78022,9 +78263,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "marsala" msgid_plural "marsala" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "marsala" +msgstr[1] "marsala" +msgstr[2] "marsala" #. ~ Description for {'str_sp': 'marsala'} #: data/json/items/comestibles/alcohol.json @@ -78034,9 +78275,9 @@ msgstr "Es un vino servido comúnmente con platos de restoranes italianos." #: data/json/items/comestibles/alcohol.json msgid "vermouth" msgid_plural "vermouth" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vermú" +msgstr[1] "vermú" +msgstr[2] "vermú" #. ~ Description for {'str_sp': 'vermouth'} #: data/json/items/comestibles/alcohol.json @@ -78050,9 +78291,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "barley wine" msgid_plural "barley wine" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vino de cebada" +msgstr[1] "vino de cebada" +msgstr[2] "vino de cebada" #. ~ Description for {'str_sp': 'barley wine'} #: data/json/items/comestibles/alcohol.json @@ -78344,9 +78585,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "burdock wine" msgid_plural "burdock wine" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vino de bardana" +msgstr[1] "vino de bardana" +msgstr[2] "vino de bardana" #. ~ Description for {'str_sp': 'burdock wine'} #: data/json/items/comestibles/alcohol.json @@ -78549,9 +78790,9 @@ msgstr "De los mejores whiskys." #: data/json/items/comestibles/alcohol.json msgid "single pot still Irish whiskey" msgid_plural "single pot still Irish whiskey" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "whisky irlandés de alambique único" +msgstr[1] "whisky irlandés de alambique único" +msgstr[2] "whisky irlandés de alambique único" #. ~ Description for {'str_sp': 'single pot still Irish whiskey'} #: data/json/items/comestibles/alcohol.json @@ -78562,9 +78803,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "cheap whiskey" msgid_plural "cheap whiskey" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "whisky barato" +msgstr[1] "whisky barato" +msgstr[2] "whisky barato" #. ~ Description for {'str_sp': 'cheap whiskey'} #: data/json/items/comestibles/alcohol.json @@ -78574,9 +78815,9 @@ msgstr "Es un whisky de mezcla muy barato." #: data/json/items/comestibles/alcohol.json msgid "Canadian whiskey" msgid_plural "Canadian whiskey" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "whisky canadiense" +msgstr[1] "whisky canadiense" +msgstr[2] "whisky canadiense" #. ~ Description for {'str_sp': 'Canadian whiskey'} #: data/json/items/comestibles/alcohol.json @@ -78586,9 +78827,9 @@ msgstr "Es un licor multigrano, hecho con pulpa de maíz y centeno." #: data/json/items/comestibles/alcohol.json msgid "sherry" msgid_plural "sherry" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "jerez" +msgstr[1] "jerez" +msgstr[2] "jerez" #. ~ Description for {'str_sp': 'sherry'} #: data/json/items/comestibles/alcohol.json @@ -78601,9 +78842,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "Bristol Cream" msgid_plural "Bristol Cream" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Bristol Cream" +msgstr[1] "Bristol Cream" +msgstr[2] "Bristol Cream" #. ~ Description for {'str_sp': 'Bristol Cream'} #: data/json/items/comestibles/alcohol.json @@ -78617,9 +78858,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "Madeira wine" msgid_plural "Madeira wine" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vino Madeira" +msgstr[1] "vino Madeira" +msgstr[2] "vino Madeira" #. ~ Description for {'str_sp': 'Madeira wine'} #: data/json/items/comestibles/alcohol.json @@ -78631,9 +78872,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "fancy hobo" msgid_plural "fancy hobo" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "indigente extravagante" +msgstr[1] "indigentes extravagantes" +msgstr[2] "indigentes extravagantes" #. ~ Description for {'str_sp': 'fancy hobo'} #: data/json/items/comestibles/alcohol.json @@ -78643,9 +78884,9 @@ msgstr "Definitivamente, tiene el gusto de una bebida de indigentes." #: data/json/items/comestibles/alcohol.json msgid "kalimotxo" msgid_plural "kalimotxo" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "jote" +msgstr[1] "jotes" +msgstr[2] "jotes" #. ~ Description for {'str_sp': 'kalimotxo'} #: data/json/items/comestibles/alcohol.json @@ -78660,9 +78901,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "bee's knees" msgid_plural "bee's knees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rodillas de abeja" +msgstr[1] "rodillas de abeja" +msgstr[2] "rodillas de abeja" #. ~ Description for {'str_sp': "bee's knees"} #: data/json/items/comestibles/alcohol.json @@ -78688,9 +78929,9 @@ msgstr "Una bebida que se hace mezclando whisky con zumo de limón." #: data/json/items/comestibles/alcohol.json msgid "honeygold brew" msgid_plural "honeygold brews" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "té mieldorado" +msgstr[1] "tés mieldorados" +msgstr[2] "tés mieldorados" #. ~ Description for honeygold brew #: data/json/items/comestibles/alcohol.json @@ -78724,9 +78965,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "spiked eggnog" msgid_plural "spiked eggnogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ponche de huevo con alcohol" +msgstr[1] "ponches de huevo con alcohol" +msgstr[2] "ponches de huevo con alcohol" #. ~ Description for spiked eggnog #: data/json/items/comestibles/alcohol.json @@ -78742,9 +78983,9 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "martini" msgid_plural "martinis" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "martini" +msgstr[1] "martini" +msgstr[2] "martini" #. ~ Description for martini #: data/json/items/comestibles/alcohol.json @@ -78758,9 +78999,9 @@ msgstr "" #: data/json/items/comestibles/bread.json msgid "donut holes" msgid_plural "donut holes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "timbit" +msgstr[1] "timbits" +msgstr[2] "timbits" #. ~ Description for {'str_sp': 'donut holes'} #: data/json/items/comestibles/bread.json @@ -78775,9 +79016,9 @@ msgstr "" #: data/json/items/comestibles/bread.json msgid "juvenile sourdough starter" msgid_plural "juvenile sourdough starters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "masa madre nueva" +msgstr[1] "masas madre nuevas" +msgstr[2] "masas madre nuevas" #. ~ Use action msg for {'str': 'juvenile sourdough starter'}. #: data/json/items/comestibles/bread.json @@ -78853,9 +79094,9 @@ msgstr "" #: data/json/items/comestibles/bread.json msgid "sourdough bread" msgid_plural "sourdough breads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pan de masa madre" +msgstr[1] "panes de masa madre" +msgstr[2] "panes de masa madre" #. ~ Description for sourdough bread #: data/json/items/comestibles/bread.json @@ -78869,9 +79110,9 @@ msgstr "" #: data/json/items/comestibles/bread.json msgid "flatbread" msgid_plural "flatbreads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pan sin levadura" +msgstr[1] "panes sin levadura" +msgstr[2] "panes sin levadura" #. ~ Description for flatbread #: data/json/items/comestibles/bread.json @@ -78917,9 +79158,9 @@ msgstr "Pan de maíz saludable y atiborra." #: data/json/items/comestibles/bread.json msgid "johnnycake" msgid_plural "johnnycakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "juanqueque" +msgstr[1] "juanqueques" +msgstr[2] "juanqueques" #. ~ Description for johnnycake #: data/json/items/comestibles/bread.json @@ -78929,9 +79170,9 @@ msgstr "Es un pedazo de pan frito denso y sabroso." #: data/json/items/comestibles/bread.json msgid "corn tortilla" msgid_plural "corn tortillas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tortilla de maíz" +msgstr[1] "tortillas de maíz" +msgstr[2] "tortillas de maíz" #. ~ Description for corn tortilla #: data/json/items/comestibles/bread.json @@ -78941,9 +79182,9 @@ msgstr "Es una masa plana y redonda hecha de harina de maíz finamente molida." #: data/json/items/comestibles/bread.json msgid "hardtack" msgid_plural "hardtacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "galleta náutica" +msgstr[1] "galletas náuticas" +msgstr[2] "galletas náuticas" #. ~ Description for hardtack #: data/json/items/comestibles/bread.json @@ -78988,9 +79229,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "mycus wine must" msgid_plural "mycus wine musts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosto de vino de mycus" +msgstr[1] "mostos de vino de mycus" +msgstr[2] "mostos de vino de mycus" #. ~ Description for mycus wine must #: data/json/items/comestibles/brewing.json @@ -79004,9 +79245,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "whiskey wort" msgid_plural "whiskey worts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosto de whisky" +msgstr[1] "mostos de whisky" +msgstr[2] "mostos de whisky" #. ~ Description for whiskey wort #: data/json/items/comestibles/brewing.json @@ -79033,9 +79274,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "fermenting gin mash" msgid_plural "fermenting gin mashes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pasta de gin fermentando" +msgstr[1] "pastas de gin fermentando" +msgstr[2] "pastas de gin fermentando" #. ~ Description for {'str': 'fermenting gin mash', 'str_pl': 'fermenting gin #. mashes'} @@ -79047,9 +79288,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "gin mash" msgid_plural "gin mashes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pasta de gin" +msgstr[1] "pastas de gin" +msgstr[2] "pastas de gin" #. ~ Description for {'str': 'gin mash', 'str_pl': 'gin mashes'} #: data/json/items/comestibles/brewing.json @@ -79063,9 +79304,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "vodka wort" msgid_plural "vodka worts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosto de vodka" +msgstr[1] "mostos de vodka" +msgstr[2] "mostos de vodka" #. ~ Description for vodka wort #: data/json/items/comestibles/brewing.json @@ -79092,9 +79333,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "rum wort" msgid_plural "rum worts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosto de ron" +msgstr[1] "mostos de ron" +msgstr[2] "mostos de ron" #. ~ Description for rum wort #: data/json/items/comestibles/brewing.json @@ -79148,9 +79389,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "dandelion wine must" msgid_plural "dandelion wine musts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosto de vino de diente de león" +msgstr[1] "mostos de vino de diente de león" +msgstr[2] "mostos de vino de diente de león" #. ~ Description for dandelion wine must #: data/json/items/comestibles/brewing.json @@ -79164,9 +79405,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "burdock wine must" msgid_plural "burdock wine musts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosto de vino de bardana" +msgstr[1] "mostos de vino de bardana" +msgstr[2] "mostos de vino de bardana" #. ~ Description for burdock wine must #: data/json/items/comestibles/brewing.json @@ -79180,9 +79421,9 @@ msgstr "" #: data/json/items/comestibles/brewing.json msgid "pine wine must" msgid_plural "pine wine musts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mosto de retsina" +msgstr[1] "mostos de retsina" +msgstr[2] "mostos de retsina" #. ~ Description for pine wine must #: data/json/items/comestibles/brewing.json @@ -79260,9 +79501,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "meat/fish" msgid_plural "meat/fish" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carne/pescado" +msgstr[1] "carne/pescado" +msgstr[2] "carne/pescado" #: data/json/items/comestibles/carnivore.json msgid "fillet of fish" @@ -79291,9 +79532,9 @@ msgstr "Es un pescado cocinado recientemente. Muy nutritivo." #: data/json/items/comestibles/carnivore.json msgid "human stomach" msgid_plural "human stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago humano" +msgstr[1] "estómagos humanos" +msgstr[2] "estómagos humanos" #. ~ Description for human stomach #: data/json/items/comestibles/carnivore.json @@ -79303,9 +79544,9 @@ msgstr "Es el estómago de un humano. Es sorprendentemente duradero." #: data/json/items/comestibles/carnivore.json msgid "large human stomach" msgid_plural "large human stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago humano grande" +msgstr[1] "estómagos humanos grandes" +msgstr[2] "estómagos humanos grandes" #. ~ Description for large human stomach #: data/json/items/comestibles/carnivore.json @@ -79317,9 +79558,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "chunk of human fat" msgid_plural "chunks of human fat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de grasa humana" +msgstr[1] "pedazos de grasa humana" +msgstr[2] "pedazos de grasa humana" #. ~ Description for {'str': 'chunk of human fat', 'str_pl': 'chunks of human #. fat'} @@ -79330,9 +79571,9 @@ msgstr "Está recién carneada de un cadáver humano." #: data/json/items/comestibles/carnivore.json msgid "human tallow" msgid_plural "human tallows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sebo humano" +msgstr[1] "sebos humanos" +msgstr[2] "sebos humanos" #. ~ Description for human tallow #: data/json/items/comestibles/carnivore.json @@ -79348,9 +79589,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "human lard" msgid_plural "human lards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "manteca humana" +msgstr[1] "mantecas humanas" +msgstr[2] "mantecas humanas" #. ~ Description for human lard #: data/json/items/comestibles/carnivore.json @@ -79378,9 +79619,9 @@ msgstr "Recién carneada de un cadáver humano." #: data/json/items/comestibles/carnivore.json msgid "cooked creep" msgid_plural "cooked creeps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "creep cocinado" +msgstr[1] "creeps cocinados" +msgstr[2] "creeps cocinados" #. ~ Description for cooked creep #: data/json/items/comestibles/carnivore.json @@ -79407,9 +79648,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "scrap of meat" msgid_plural "scraps of meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de carne" +msgstr[1] "pedazos de carne" +msgstr[2] "pedazos de carne" #. ~ Description for {'str': 'scrap of meat', 'str_pl': 'scraps of meat'} #: data/json/items/comestibles/carnivore.json @@ -79423,9 +79664,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "chunk of mutant meat" msgid_plural "chunks of mutant meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de carne mutante" +msgstr[1] "pedazos de carne mutante" +msgstr[2] "pedazos de carne mutante" #. ~ Description for {'str': 'chunk of mutant meat', 'str_pl': 'chunks of #. mutant meat'} @@ -79439,9 +79680,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "scrap of mutant meat" msgid_plural "scraps of mutant meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de carne mutante" +msgstr[1] "pedazos de carne mutante" +msgstr[2] "pedazos de carne mutante" #. ~ Description for {'str': 'scrap of mutant meat', 'str_pl': 'scraps of #. mutant meat'} @@ -79455,9 +79696,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "mutant humanoid meat" msgid_plural "mutant humanoid meats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carne de mutante humanoide" +msgstr[1] "carnes de mutante humanoide" +msgstr[2] "carnes de mutante humanoide" #. ~ Description for mutant humanoid meat #: data/json/items/comestibles/carnivore.json @@ -79470,9 +79711,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "cooked cretin" msgid_plural "cooked cretins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cretino cocinado" +msgstr[1] "cretinos cocinados" +msgstr[2] "cretinos cocinados" #. ~ Description for cooked cretin #: data/json/items/comestibles/carnivore.json @@ -79500,16 +79741,16 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "cooked scrap of meat" msgid_plural "cooked scraps of meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de carne cocinada" +msgstr[1] "pedazos de carne cocinada" +msgstr[2] "pedazos de carne cocinada" #: data/json/items/comestibles/carnivore.json msgid "cooked mutant meat" msgid_plural "cooked mutant meats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carne mutante cocinada" +msgstr[1] "carnes mutantes cocinadas" +msgstr[2] "carnes mutantes cocinadas" #. ~ Description for cooked mutant meat #: data/json/items/comestibles/carnivore.json @@ -79521,16 +79762,16 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "cooked scrap of mutant meat" msgid_plural "cooked scraps of mutant meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de carne mutante cocinada" +msgstr[1] "pedazos de carne mutante cocinada" +msgstr[2] "pedazos de carne mutante cocinada" #: data/json/items/comestibles/carnivore.json msgid "raw offal" msgid_plural "raw offals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "achura cruda" +msgstr[1] "achuras crudas" +msgstr[2] "achuras crudas" #. ~ Description for raw offal #: data/json/items/comestibles/carnivore.json @@ -79597,9 +79838,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "stomach" msgid_plural "stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago" +msgstr[1] "estómagos" +msgstr[2] "estómagos" #. ~ Description for stomach #: data/json/items/comestibles/carnivore.json @@ -79610,9 +79851,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "large stomach" msgid_plural "large stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago grande" +msgstr[1] "estómagos grandes" +msgstr[2] "estómagos grandes" #. ~ Description for large stomach #: data/json/items/comestibles/carnivore.json @@ -79642,9 +79883,9 @@ msgstr[2] "cecinas de hombre" #: data/json/items/comestibles/carnivore.json msgid "monster jerky" msgid_plural "monster jerky" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "charqui de monstruo" +msgstr[1] "charqui de monstruo" +msgstr[2] "charqui de monstruo" #. ~ Description for {'str_sp': 'meat jerky'} #: data/json/items/comestibles/carnivore.json @@ -79680,9 +79921,9 @@ msgstr[2] "carnes ahumadas" #: data/json/items/comestibles/carnivore.json msgid "smoked sucker" msgid_plural "smoked sucker" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cabrón ahumado" +msgstr[1] "cabrón ahumado" +msgstr[2] "cabrón ahumado" #. ~ Conditional name for smoked meat when COMPONENT_ID matches mutant #. ~ Conditional name for canned meat when COMPONENT_ID matches mutant @@ -79695,9 +79936,9 @@ msgstr[2] "" #, c-format msgid "%s, mutant" msgid_plural "%s, mutant" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%s, mutante" +msgstr[1] "%s, mutante" +msgstr[2] "%s, mutante" #. ~ Description for smoked meat #: data/json/items/comestibles/carnivore.json @@ -79727,9 +79968,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "piece of raw lung" msgid_plural "pieces of raw lung" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de pulmón crudo" +msgstr[1] "pedazos de pulmón crudo" +msgstr[2] "pedazos de pulmón crudo" #. ~ Description for {'str': 'piece of raw lung', 'str_pl': 'pieces of raw #. lung'} @@ -79746,9 +79987,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "raw liver" msgid_plural "raw livers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hígado crudo" +msgstr[1] "hígados crudos" +msgstr[2] "hígados crudos" #. ~ Description for raw liver #: data/json/items/comestibles/carnivore.json @@ -79764,9 +80005,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "raw brains" msgid_plural "raw brains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cerebro crudo" +msgstr[1] "cerebros crudos" +msgstr[2] "cerebros crudos" #. ~ Description for {'str_sp': 'raw brains'} #: data/json/items/comestibles/carnivore.json @@ -79776,9 +80017,9 @@ msgstr "Es el cerebro de un animal. No vas a querer comerte esto crudo..." #: data/json/items/comestibles/carnivore.json msgid "raw kidney" msgid_plural "raw kidneys" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "riñón crudo" +msgstr[1] "riñones crudos" +msgstr[2] "riñones crudos" #. ~ Description for raw kidney #: data/json/items/comestibles/carnivore.json @@ -79792,9 +80033,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "raw sweetbread" msgid_plural "raw sweetbreads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "molleja cruda" +msgstr[1] "mollejas crudas" +msgstr[2] "mollejas crudas" #. ~ Description for raw sweetbread #: data/json/items/comestibles/carnivore.json @@ -79891,9 +80132,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "chunk of mutant fat" msgid_plural "chunks of mutant fat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de grasa mutante" +msgstr[1] "pedazos de grasa mutante" +msgstr[2] "pedazos de grasa mutante" #. ~ Description for {'str': 'chunk of mutant fat', 'str_pl': 'chunks of #. mutant fat'} @@ -79908,9 +80149,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "mutant tallow" msgid_plural "mutant tallows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sebo mutante" +msgstr[1] "sebos mutantes" +msgstr[2] "sebos mutantes" #. ~ Description for mutant tallow #: data/json/items/comestibles/carnivore.json @@ -79926,9 +80167,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "mutant lard" msgid_plural "mutant lards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "manteca mutante" +msgstr[1] "mantecas mutantes" +msgstr[2] "mantecas mutantes" #. ~ Description for mutant lard #: data/json/items/comestibles/carnivore.json @@ -79944,9 +80185,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "chunk of mutant humanoid fat" msgid_plural "chunks of mutant humanoid fat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de grasa mutante humanoide" +msgstr[1] "pedazos de grasa mutante humanoide" +msgstr[2] "pedazos de grasa mutante humanoide" #. ~ Description for {'str': 'chunk of mutant humanoid fat', 'str_pl': 'chunks #. of mutant humanoid fat'} @@ -79957,9 +80198,9 @@ msgstr "Es grasa recién carneada de un humanoide muy mutado." #: data/json/items/comestibles/carnivore.json msgid "mutant humanoid tallow" msgid_plural "mutant humanoid tallows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sebo de mutante humanoide" +msgstr[1] "sebos de mutante humanoide" +msgstr[2] "sebos de mutante humanoide" #. ~ Description for mutant humanoid tallow #: data/json/items/comestibles/carnivore.json @@ -79975,9 +80216,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "mutant humanoid lard" msgid_plural "mutant humanoid lards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "manteca de mutante humanoide" +msgstr[1] "mantecas de mutante humanoide" +msgstr[2] "mantecas de mutante humanoide" #. ~ Description for mutant humanoid lard #: data/json/items/comestibles/carnivore.json @@ -80077,9 +80318,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "large boiled stomach" msgid_plural "large boiled stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago grande hervido" +msgstr[1] "estómagos grandes hervidos" +msgstr[2] "estómagos grandes hervidos" #. ~ Description for large boiled stomach #: data/json/items/comestibles/carnivore.json @@ -80092,9 +80333,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "boiled large human stomach" msgid_plural "boiled large human stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago humano grande hervido" +msgstr[1] "estómagos humanos grandes hervidos" +msgstr[2] "estómagos humanos grandes hervidos" #. ~ Description for {'str': 'boiled large human stomach'} #: data/json/items/comestibles/carnivore.json @@ -80108,9 +80349,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "boiled stomach" msgid_plural "boiled stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago hervido" +msgstr[1] "estómagos hervidos" +msgstr[2] "estómagos hervidos" #. ~ Description for {'str': 'boiled stomach'} #: data/json/items/comestibles/carnivore.json @@ -80124,9 +80365,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "boiled human stomach" msgid_plural "boiled human stomachs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "estómago humano hervido" +msgstr[1] "estómagos humanos hervidos" +msgstr[2] "estómagos humanos hervidos" #. ~ Description for {'str': 'boiled human stomach'} #: data/json/items/comestibles/carnivore.json @@ -80156,9 +80397,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "tainted hide" msgid_plural "tainted hides" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pellejo contaminado" +msgstr[1] "pellejos contaminados" +msgstr[2] "pellejos contaminados" #. ~ Description for tainted hide #: data/json/items/comestibles/carnivore.json @@ -80172,9 +80413,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "raw human skin" msgid_plural "raw human skins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pellejo humano crudo" +msgstr[1] "pellejos humanos crudos" +msgstr[2] "pellejos humanos crudos" #. ~ Description for raw human skin #: data/json/items/comestibles/carnivore.json @@ -80207,9 +80448,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "tainted pelt" msgid_plural "tainted pelts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pelaje contaminado" +msgstr[1] "pelajes contaminados" +msgstr[2] "pelajes contaminados" #. ~ Description for tainted pelt #: data/json/items/comestibles/carnivore.json @@ -80225,9 +80466,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "raw human pelt" msgid_plural "raw human pelts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pelaje humano crudo" +msgstr[1] "pelajes humanos crudos" +msgstr[2] "pelajes humanos crudos" #. ~ Description for raw human pelt #: data/json/items/comestibles/carnivore.json @@ -80243,9 +80484,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "seeping heart" msgid_plural "seeping hearts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "corazón con agujeritos" +msgstr[1] "corazones con agujeritos" +msgstr[2] "corazones con agujeritos" #. ~ Description for seeping heart #: data/json/items/comestibles/carnivore.json @@ -80259,9 +80500,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "putrid heart" msgid_plural "putrid hearts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "corazón pútrido" +msgstr[1] "corazones pútridos" +msgstr[2] "corazones pútridos" #. ~ Description for putrid heart #: data/json/items/comestibles/carnivore.json @@ -80282,9 +80523,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "desiccated putrid heart" msgid_plural "desiccated putrid hearts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "corazón pútrido disecado" +msgstr[1] "corazones pútridos disecados" +msgstr[2] "corazones pútridos disecados" #. ~ Description for desiccated putrid heart #: data/json/items/comestibles/carnivore.json @@ -80300,9 +80541,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "alien fronds" msgid_plural "alien fronds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fronda alienígena" +msgstr[1] "fronda alienígena" +msgstr[2] "fronda alienígena" #. ~ Description for {'str_sp': 'alien fronds'} #: data/json/items/comestibles/carnivore.json @@ -80319,9 +80560,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "leech flower" msgid_plural "leech flowers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flor chupasangre" +msgstr[1] "flores chupasangre" +msgstr[2] "flores chupasangre" #. ~ Use action activation_message for leech flower. #: data/json/items/comestibles/carnivore.json @@ -80347,9 +80588,9 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "leech bark" msgid_plural "scraps of leech bark" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "corteza de planta chupasangre" +msgstr[1] "pedazos de corteza de planta chupasangre" +msgstr[2] "pedazos de corteza de planta chupasangre" #. ~ Description for {'str': 'leech bark', 'str_pl': 'scraps of leech bark'} #: data/json/items/comestibles/carnivore.json @@ -80378,9 +80619,9 @@ msgstr "" #: data/json/items/comestibles/dairy.json msgid "shelf stable milk" msgid_plural "shelf stable milk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche larga vida" +msgstr[1] "leche larga vida" +msgstr[2] "leche larga vida" #. ~ Description for {'str_sp': 'shelf stable milk'} #: data/json/items/comestibles/dairy.json @@ -80396,9 +80637,9 @@ msgstr "" #: data/json/items/comestibles/dairy.json msgid "evaporated milk" msgid_plural "evaporated milk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche evaporada" +msgstr[1] "leche evaporada" +msgstr[2] "leche evaporada" #. ~ Description for {'str_sp': 'evaporated milk'} #: data/json/items/comestibles/dairy.json @@ -80409,9 +80650,9 @@ msgstr "" #: data/json/items/comestibles/dairy.json msgid "yogurt" msgid_plural "yogurts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "yogur" +msgstr[1] "yogures" +msgstr[2] "yogures" #. ~ Description for yogurt #: data/json/items/comestibles/dairy.json @@ -80421,9 +80662,9 @@ msgstr "Delicioso producto lácteo fermentado. Tiene gusto a vainilla." #: data/json/items/comestibles/dairy.json msgid "butter" msgid_plural "butter" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "manteca" +msgstr[1] "manteca" +msgstr[2] "manteca" #. ~ Description for {'str_sp': 'butter'} #: data/json/items/comestibles/dairy.json @@ -80508,9 +80749,9 @@ msgstr "Un pedazo amarillo de queso procesado." #: data/json/items/comestibles/dairy.json msgid "quesadilla" msgid_plural "quesadillas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "quesadilla" +msgstr[1] "quesadillas" +msgstr[2] "quesadillas" #. ~ Description for quesadilla #: data/json/items/comestibles/dairy.json @@ -80562,9 +80803,9 @@ msgstr "Exprimida de manzanas frescas. Sabrosa y nutritiva." #: data/json/items/comestibles/drink.json msgid "almond milk" msgid_plural "almond milks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche de almendra" +msgstr[1] "leche de almendra" +msgstr[2] "leche de almendra" #. ~ Description for {'str': 'almond milk'} #: data/json/items/comestibles/drink.json @@ -80578,9 +80819,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "soy milk" msgid_plural "soy milks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche de soja" +msgstr[1] "leche de soja" +msgstr[2] "leche de soja" #. ~ Description for soy milk #: data/json/items/comestibles/drink.json @@ -80673,9 +80914,9 @@ msgstr "Es una mezcla tradicional del sur asiático, de leche y té." #: data/json/items/comestibles/drink.json msgid "chamomile tea" msgid_plural "chamomile tea" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "té de manzanliia" +msgstr[1] "té de manzanliia" +msgstr[2] "té de manzanliia" #. ~ Description for {'str_sp': 'chamomile tea'} #: data/json/items/comestibles/drink.json @@ -80706,9 +80947,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "coffee substitute" msgid_plural "coffee substitute" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sucedáneo de café" +msgstr[1] "sucedáneo de café" +msgstr[2] "sucedáneo de café" #. ~ Description for {'str_sp': 'coffee substitute'} #: data/json/items/comestibles/drink.json @@ -80724,9 +80965,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "chicory brew" msgid_plural "chicory brew" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "infusión de achicoria" +msgstr[1] "infusión de achicoria" +msgstr[2] "infusión de achicoria" #. ~ Description for {'str_sp': 'chicory brew'} #: data/json/items/comestibles/drink.json @@ -80824,9 +81065,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "dandelion and burdock tea" msgid_plural "dandelion and burdock tea" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "té de diente de león y bardana" +msgstr[1] "té de diente de león y bardana" +msgstr[2] "té de diente de león y bardana" #. ~ Description for {'str_sp': 'dandelion and burdock tea'} #: data/json/items/comestibles/drink.json @@ -80841,9 +81082,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "eggnog" msgid_plural "eggnogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ponche de huevo" +msgstr[1] "ponche de huevo" +msgstr[2] "ponche de huevo" #. ~ Description for eggnog #: data/json/items/comestibles/drink.json @@ -80980,9 +81221,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "lotus tea" msgid_plural "lotus tea" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "té de loto" +msgstr[1] "té de loto" +msgstr[2] "té de loto" #. ~ Description for {'str_sp': 'lotus tea'} #: data/json/items/comestibles/drink.json @@ -81016,9 +81257,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "reconstituted milk" msgid_plural "reconstituted milk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche rehidratada" +msgstr[1] "leche rehidratada" +msgstr[2] "leche rehidratada" #. ~ Description for {'str_sp': 'reconstituted milk'} #: data/json/items/comestibles/drink.json @@ -81179,9 +81420,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "spurge tea" msgid_plural "spurge tea" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "té de euforbio" +msgstr[1] "té de euforbio" +msgstr[2] "té de euforbio" #. ~ Description for {'str_sp': 'spurge tea'} #: data/json/items/comestibles/drink.json @@ -81195,9 +81436,9 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "rehydration drink" msgid_plural "rehydration drinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bebida hidratante" +msgstr[1] "bebida hidratante" +msgstr[2] "bebida hidratante" #. ~ Description for rehydration drink #: data/json/items/comestibles/drink.json @@ -81490,9 +81731,9 @@ msgstr "" #: data/json/items/comestibles/drink_other.json msgid "imitation peanutbutter" msgid_plural "imitation peanutbutters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "imitación de mantequilla de maní" +msgstr[1] "imitación de mantequilla de maní" +msgstr[2] "imitación de mantequilla de maní" #. ~ Description for imitation peanutbutter #: data/json/items/comestibles/drink_other.json @@ -81518,9 +81759,9 @@ msgstr "" #: data/json/items/comestibles/drink_other.json msgid "vegetable cooking oil" msgid_plural "vegetable cooking oil" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aceite vegetal de cocina" +msgstr[1] "aceite vegetal de cocina" +msgstr[2] "aceite vegetal de cocina" #. ~ Description for {'str_sp': 'vegetable cooking oil'} #: data/json/items/comestibles/drink_other.json @@ -81600,9 +81841,9 @@ msgstr "Es un nutritivo huevo, puesto por algún pájaro." #: data/json/items/comestibles/egg.json msgid "chicken egg" msgid_plural "chicken eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de gallina" +msgstr[1] "huevos de gallina" +msgstr[2] "huevos de gallina" #: data/json/items/comestibles/egg.json msgid "unfertilized bird egg" @@ -81621,51 +81862,51 @@ msgstr "" #: data/json/items/comestibles/egg.json msgid "grouse egg" msgid_plural "grouse eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de urogallo" +msgstr[1] "huevos de urogallo" +msgstr[2] "huevos de urogallo" #: data/json/items/comestibles/egg.json msgid "crow egg" msgid_plural "crow eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de cuervo" +msgstr[1] "huevos de cuervo" +msgstr[2] "huevos de cuervo" #: data/json/items/comestibles/egg.json msgid "duck egg" msgid_plural "duck eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de pato" +msgstr[1] "huevos de pato" +msgstr[2] "huevos de pato" #: data/json/items/comestibles/egg.json msgid "goose egg" msgid_plural "goose eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de ganso" +msgstr[1] "huevos de ganso" +msgstr[2] "huevos de ganso" #: data/json/items/comestibles/egg.json msgid "turkey egg" msgid_plural "turkey eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de pavo" +msgstr[1] "huevos de pavo" +msgstr[2] "huevos de pavo" #: data/json/items/comestibles/egg.json msgid "pheasant egg" msgid_plural "pheasant eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de faisán" +msgstr[1] "huevos de faisán" +msgstr[2] "huevos de faisán" #: data/json/items/comestibles/egg.json msgid "cockatrice egg" msgid_plural "cockatrice eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de cocatriz" +msgstr[1] "huevos de cocatriz" +msgstr[2] "huevos de cocatriz" #: data/json/items/comestibles/egg.json msgid "reptile egg" @@ -81714,9 +81955,9 @@ msgstr "" #: data/json/items/comestibles/egg.json msgid "roach egg" msgid_plural "roach eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de cucaracha" +msgstr[1] "huevos de cucaracha" +msgstr[2] "huevos de cucaracha" #. ~ Description for roach egg #: data/json/items/comestibles/egg.json @@ -81728,9 +81969,9 @@ msgstr "" #: data/json/items/comestibles/egg.json msgid "insect egg" msgid_plural "insect eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de insecto" +msgstr[1] "huevos de insecto" +msgstr[2] "huevos de insecto" #. ~ Description for insect egg #: data/json/items/comestibles/egg.json @@ -81740,9 +81981,9 @@ msgstr "" #: data/json/items/comestibles/egg.json msgid "razorclaw roe" msgid_plural "razorclaw roes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hueva de garrafilada" +msgstr[1] "huevas de garrafilada" +msgstr[2] "huevas de garrafilada" #. ~ Description for razorclaw roe #: data/json/items/comestibles/egg.json @@ -81752,9 +81993,9 @@ msgstr "Son unos huevos de garrafilada. Una exquisitez postapocalíptica." #: data/json/items/comestibles/egg.json msgid "roe" msgid_plural "roes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hueva" +msgstr[1] "huevas" +msgstr[2] "huevas" #. ~ Description for roe #: data/json/items/comestibles/egg.json @@ -81801,9 +82042,9 @@ msgstr "" #: data/json/items/comestibles/egg.json msgid "pickled egg" msgid_plural "pickled eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo al escabeche" +msgstr[1] "huevos al escabeche" +msgstr[2] "huevos al escabeche" #. ~ Description for pickled egg #: data/json/items/comestibles/egg.json @@ -81813,13 +82054,61 @@ msgstr "" "Es huevo al escabeche. Bastante salado, pero tiene buen sabor y dura mucho " "tiempo." -#: data/json/items/comestibles/frozen.json -msgid "milkshake" -msgid_plural "milkshakes" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" msgstr[0] "" msgstr[1] "" msgstr[2] "" +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + +#: data/json/items/comestibles/frozen.json +msgid "milkshake" +msgid_plural "milkshakes" +msgstr[0] "licuado" +msgstr[1] "licuados" +msgstr[2] "licuados" + #. ~ Description for {'str': 'milkshake'} #: data/json/items/comestibles/frozen.json msgid "" @@ -81832,9 +82121,9 @@ msgstr "" #: data/json/items/comestibles/frozen.json msgid "fast food milkshake" msgid_plural "fast food milkshakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "licuado de restaurant" +msgstr[1] "licuados de restaurant" +msgstr[2] "licuados de restaurant" #. ~ Description for {'str': 'fast food milkshake'} #: data/json/items/comestibles/frozen.json @@ -81848,9 +82137,9 @@ msgstr "" #: data/json/items/comestibles/frozen.json msgid "deluxe milkshake" msgid_plural "deluxe milkshakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "licuado de lujo" +msgstr[1] "licuados de lujo" +msgstr[2] "licuados de lujo" #. ~ Description for {'str': 'deluxe milkshake'} #: data/json/items/comestibles/frozen.json @@ -81864,9 +82153,9 @@ msgstr "" #: data/json/items/comestibles/frozen.json msgid "ice cream" msgid_plural "ice cream scoops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "helado" +msgstr[1] "bolas de helado" +msgstr[2] "bolas de helado" #. ~ Description for {'str': 'ice cream', 'str_pl': 'ice cream scoops'} #: data/json/items/comestibles/frozen.json @@ -81878,9 +82167,9 @@ msgstr "" #: data/json/items/comestibles/frozen.json msgid "dairy dessert" msgid_plural "dairy dessert scoops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "postre lácteo" +msgstr[1] "bolas de postre lácteo" +msgstr[2] "bolas de postre lácteo" #. ~ Description for {'str': 'dairy dessert', 'str_pl': 'dairy dessert #. scoops'} @@ -81911,9 +82200,9 @@ msgstr "Es helado con pedacitos de chocolate, u otro sabor mezclado." #: data/json/items/comestibles/frozen.json msgid "fruity ice cream" msgid_plural "fruity ice cream scoops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "helado frutal" +msgstr[1] "bolas de helado frutal" +msgstr[2] "bolas de helado frutal" #. ~ Description for {'str': 'fruity ice cream', 'str_pl': 'fruity ice cream #. scoops'} @@ -81928,9 +82217,9 @@ msgstr "" #: data/json/items/comestibles/frozen.json msgid "frozen custard" msgid_plural "frozen custard scoops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "candy" +msgstr[1] "bolas de candy" +msgstr[2] "bolas de candy" #. ~ Description for {'str': 'frozen custard', 'str_pl': 'frozen custard #. scoops'} @@ -81963,9 +82252,9 @@ msgstr "" #: data/json/items/comestibles/frozen.json msgid "sorbet" msgid_plural "sorbet scoops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sorbete" +msgstr[1] "bolas de sorbete" +msgstr[2] "bolas de sorbete" #. ~ Description for {'str': 'sorbet', 'str_pl': 'sorbet scoops'} #: data/json/items/comestibles/frozen.json @@ -81975,9 +82264,9 @@ msgstr "Es un simple postre helado hecho con agua y jugo de fruto." #: data/json/items/comestibles/frozen.json msgid "gelato" msgid_plural "gelato scoops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gelato" +msgstr[1] "bolas de gelato" +msgstr[2] "bolas de gelato" #. ~ Description for {'str': 'gelato', 'str_pl': 'gelato scoops'} #: data/json/items/comestibles/frozen.json @@ -82053,9 +82342,9 @@ msgstr "Son rodajas de piña enlatados con agua. Bastante sabrosos." #: data/json/items/comestibles/fruit_dishes.json msgid "lemonade drink mix" msgid_plural "lemonade drink mix" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bebida de limonada" +msgstr[1] "bebida de limonada" +msgstr[2] "bebida de limonada" #. ~ Description for {'str_sp': 'lemonade drink mix'} #: data/json/items/comestibles/fruit_dishes.json @@ -82155,9 +82444,9 @@ msgstr "" #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated rose hips" msgid_plural "irradiated rose hips" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "escaramujo irradiado" +msgstr[1] "escaramujos irradiados" +msgstr[2] "escaramujos irradiados" #. ~ Description for {'str_sp': 'irradiated rose hips'} #: data/json/items/comestibles/irradiated_fruit.json @@ -82188,9 +82477,9 @@ msgstr "" #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated mulberry" msgid_plural "irradiated mulberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mora irradiada" +msgstr[1] "moras irradiadas" +msgstr[2] "moras irradiadas" #. ~ Description for {'str': 'irradiated mulberry', 'str_pl': 'irradiated #. mulberries'} @@ -82205,9 +82494,9 @@ msgstr "" #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated huckleberry" msgid_plural "irradiated huckleberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arándano agrio irradiado" +msgstr[1] "arándanos agrios irradiados" +msgstr[2] "arándanos agrios irradiados" #. ~ Description for {'str': 'irradiated huckleberry', 'str_pl': 'irradiated #. huckleberries'} @@ -82581,9 +82870,9 @@ msgstr "" #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated apricot" msgid_plural "irradiated apricots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "damasco irradiado" +msgstr[1] "damascos irradiados" +msgstr[2] "damascos irradiados" #. ~ Description for irradiated apricot #: data/json/items/comestibles/irradiated_fruit.json @@ -82613,9 +82902,9 @@ msgstr "" #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated cabbage" msgid_plural "irradiated cabbages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "repollo irradiado" +msgstr[1] "repollos irradiados" +msgstr[2] "repollos irradiados" #. ~ Description for irradiated cabbage #: data/json/items/comestibles/irradiated_veggy.json @@ -82726,9 +83015,9 @@ msgstr "" #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated pumpkin" msgid_plural "irradiated pumpkins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "calabaza irradiada" +msgstr[1] "calabazas irradiadas" +msgstr[2] "calabazas irradiadas" #. ~ Description for irradiated pumpkin #: data/json/items/comestibles/irradiated_veggy.json @@ -82961,9 +83250,9 @@ msgstr "Una galleta para ir picando algo." #: data/json/items/comestibles/junkfood.json msgid "chocolate-covered pretzel" msgid_plural "chocolate-covered pretzels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pretzel con chocolate" +msgstr[1] "pretzels con chocolate" +msgstr[2] "pretzels con chocolate" #. ~ Description for chocolate-covered pretzel #: data/json/items/comestibles/junkfood.json @@ -83040,9 +83329,9 @@ msgstr "Es un puñado de golosinas coloridas rellenas con chocolate." #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json msgid "chewy candy" msgid_plural "chewy candy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caramelos masticables" +msgstr[1] "caramelos masticables" +msgstr[2] "caramelos masticables" #. ~ Description for {'str_sp': 'chewy candy'} #: data/json/items/comestibles/junkfood.json @@ -83101,6 +83390,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "galleta" @@ -83229,9 +83519,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "Necco wafers" msgid_plural "Necco wafers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "galleta Necco" +msgstr[1] "galletas Necco" +msgstr[2] "galletas Necco" #. ~ Description for {'str_sp': 'Necco wafers'} #: data/json/items/comestibles/junkfood.json @@ -83322,9 +83612,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "cheese nachos" msgid_plural "cheese nachos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nachos de queso" +msgstr[1] "nachos de queso" +msgstr[2] "nachos de queso" #. ~ Description for {'str_sp': 'cheese nachos'} #: data/json/items/comestibles/junkfood.json @@ -83338,9 +83628,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "meat nachos" msgid_plural "meat nachos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nachos de carne" +msgstr[1] "nachos de carne" +msgstr[2] "nachos de carne" #. ~ Conditional name for {'str_sp': 'meat nachos'} when FLAG matches #. CANNIBALISM @@ -83356,9 +83646,9 @@ msgstr[2] "nachos niño" #: data/json/items/comestibles/junkfood.json msgid "nachos con chupacabra" msgid_plural "nachos con chupacabra" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nachos con chupacabra" +msgstr[1] "nachos con chupacabra" +msgstr[2] "nachos con chupacabra" #. ~ Description for {'str_sp': 'meat nachos'} #: data/json/items/comestibles/junkfood.json @@ -83372,9 +83662,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "meat nachos with cheese" msgid_plural "meat nachos with cheese" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nachos de carne con queso" +msgstr[1] "nachos de carne con queso" +msgstr[2] "nachos de carne con queso" #. ~ Conditional name for {'str_sp': 'meat nachos with cheese'} when FLAG #. matches CANNIBALISM @@ -83390,9 +83680,9 @@ msgstr[2] "nachos niño con queso" #: data/json/items/comestibles/junkfood.json msgid "cheese and chupacabra nachos" msgid_plural "cheese and chupacabra nachos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nachos de queso y chupacabra" +msgstr[1] "nachos de queso y chupacabra" +msgstr[2] "nachos de queso y chupacabra" #. ~ Description for {'str_sp': 'meat nachos with cheese'} #: data/json/items/comestibles/junkfood.json @@ -83417,9 +83707,9 @@ msgstr "Cerdo seco y salado. Tiene buen sabor, pero comerlo te da sed." #: data/json/items/comestibles/junkfood.json msgid "microwave burrito" msgid_plural "microwave burritos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "burrito para microondas" +msgstr[1] "burrito para microondas" +msgstr[2] "burrito para microondas" #. ~ Description for microwave burrito #: data/json/items/comestibles/junkfood.json @@ -83466,9 +83756,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "deep-fried chicken" msgid_plural "deep-fried chickens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pollo frito" +msgstr[1] "pollos fritos" +msgstr[2] "pollos fritos" #. ~ Description for deep-fried chicken #: data/json/items/comestibles/junkfood.json @@ -83506,9 +83796,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "cooked corn dog" msgid_plural "cooked corn dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salchicha empanizada cocinada" +msgstr[1] "salchichas empanizadas cocinadas" +msgstr[2] "salchichas empanizadas cocinadas" #. ~ Description for cooked corn dog #: data/json/items/comestibles/junkfood.json @@ -83522,9 +83812,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "homemade corn dog" msgid_plural "homemade corn dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salchicha empanizada casera" +msgstr[1] "salchichas empanizadas caseras" +msgstr[2] "salchichas empanizadas caseras" #. ~ Description for homemade corn dog #: data/json/items/comestibles/junkfood.json @@ -83606,9 +83896,9 @@ msgstr "Son aros de cebolla fritos. Crujientes y deliciosos." #: data/json/items/comestibles/junkfood.json msgid "uncooked hot dog" msgid_plural "uncooked hot dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pancho sin cocinar" +msgstr[1] "panchos sin cocinar" +msgstr[2] "panchos sin cocinar" #. ~ Description for {'str': 'uncooked hot dog'} #: data/json/items/comestibles/junkfood.json @@ -83622,9 +83912,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "campfire hot dog" msgid_plural "campfire hot dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salchicha de fogata" +msgstr[1] "salchichas de fogata" +msgstr[2] "salchichas de fogata" #. ~ Description for {'str': 'campfire hot dog'} #: data/json/items/comestibles/junkfood.json @@ -83638,9 +83928,9 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "cooked hot dog" msgid_plural "cooked hot dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pancho cocinado" +msgstr[1] "panchos cocinados" +msgstr[2] "panchos cocinados" #. ~ Description for {'str': 'cooked hot dog'} #: data/json/items/comestibles/junkfood.json @@ -83670,17 +83960,17 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "raw sausage" msgid_plural "raw sausages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salchicha cruda" +msgstr[1] "salchichas crudas" +msgstr[2] "salchichas crudas" #. ~ Conditional name for raw sausage when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "raw Mannwurst" msgid_plural "raw Mannwursts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Juannwurst cruda" +msgstr[1] "Juannwurst crudas" +msgstr[2] "Juannwurst crudas" #. ~ Conditional name for raw sausage when COMPONENT_ID matches mutant #. ~ Conditional name for smoked sausage when COMPONENT_ID matches mutant @@ -83691,9 +83981,9 @@ msgstr[2] "" #, c-format msgid "sinister %s" msgid_plural "sinister %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "siniestro %s" +msgstr[1] "siniestros %s" +msgstr[2] "siniestros %s" #. ~ Description for raw sausage #: data/json/items/comestibles/meat_dishes.json @@ -83703,17 +83993,17 @@ msgstr "Es una salchicha grande y cruda, lista para ahumar o para cocinar." #: data/json/items/comestibles/meat_dishes.json msgid "smoked sausage" msgid_plural "smoked sausages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salchicha ahumada" +msgstr[1] "salchichas ahumadas" +msgstr[2] "salchichas ahumadas" #. ~ Conditional name for smoked sausage when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "smoked Mannwurst" msgid_plural "smoked Mannwursts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Juannwurst ahumada" +msgstr[1] "Juannwurst ahumadas" +msgstr[2] "Juannwurst ahumadas" #. ~ Description for smoked sausage #: data/json/items/comestibles/meat_dishes.json @@ -83725,17 +84015,17 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "cooked sausage" msgid_plural "cooked sausages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salchicha cocinada" +msgstr[1] "salchichas cocinadas" +msgstr[2] "salchichas cocinadas" #. ~ Conditional name for cooked sausage when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "cooked Mannwurst" msgid_plural "cooked Mannwursts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Juannwurst cocinada" +msgstr[1] "Juannwurst cocinadas" +msgstr[2] "Juannwurst cocinadas" #. ~ Description for cooked sausage #: data/json/items/comestibles/meat_dishes.json @@ -83791,17 +84081,17 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "bratwurst" msgid_plural "bratwursts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bratwurst" +msgstr[1] "bratwursts" +msgstr[2] "bratwursts" #. ~ Conditional name for {'str': 'bratwurst'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "Mannbrat" msgid_plural "Mannbrats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Juannbrat" +msgstr[1] "Juannbrats" +msgstr[2] "Juannbrats" #. ~ Conditional name for {'str': 'bratwurst'} when COMPONENT_ID matches #. mutant @@ -83809,9 +84099,9 @@ msgstr[2] "" #, c-format msgid "baleful %s" msgid_plural "baleful %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torvo %s" +msgstr[1] "torvos %s" +msgstr[2] "torvos %s" #. ~ Description for {'str': 'bratwurst'} #: data/json/items/comestibles/meat_dishes.json @@ -83825,9 +84115,9 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "royal beef" msgid_plural "royal beef" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carne real" +msgstr[1] "carnes reales" +msgstr[2] "carnes reales" #. ~ Description for {'str_sp': 'royal beef'} #: data/json/items/comestibles/meat_dishes.json @@ -83883,9 +84173,9 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "raw wasteland sausage" msgid_plural "raw wasteland sausages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salchicha baldía cruda" +msgstr[1] "salchichas baldías crudas" +msgstr[2] "salchichas baldías crudas" #. ~ Description for raw wasteland sausage #: data/json/items/comestibles/meat_dishes.json @@ -83926,9 +84216,9 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "glazed tenderloins" msgid_plural "glazed tenderloins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lomito glaseado" +msgstr[1] "lomitos glaseados" +msgstr[2] "lomitos glaseados" #. ~ Conditional name for {'str_sp': 'glazed tenderloins'} when COMPONENT_ID #. matches mutant @@ -83936,9 +84226,9 @@ msgstr[2] "" #, c-format msgid "grisly %s" msgid_plural "grisly %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "horripilante %s" +msgstr[1] "horripilantes %s" +msgstr[2] "horripilantes %s" #. ~ Description for {'str_sp': 'glazed tenderloins'} #: data/json/items/comestibles/meat_dishes.json @@ -83954,27 +84244,27 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "currywurst" msgid_plural "currywursts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "currywurst" +msgstr[1] "currywursts" +msgstr[2] "currywursts" #. ~ Conditional name for currywurst when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "cheapskate %s" msgid_plural "cheapskate %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "miserable %s" +msgstr[1] "miserables %s" +msgstr[2] "miserables %s" #. ~ Conditional name for currywurst when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "bloodcurdling %s" msgid_plural "bloodcurdling %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espeluznante %s" +msgstr[1] "espeluznantes %s" +msgstr[2] "espeluznantes %s" #. ~ Description for currywurst #: data/json/items/comestibles/meat_dishes.json @@ -83997,18 +84287,18 @@ msgstr[2] "áspics" #, c-format msgid "abomination %s" msgid_plural "abomination %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "abominación %s" +msgstr[1] "abominaciones %s" +msgstr[2] "abominaciones %s" #. ~ Conditional name for {'str': 'aspic'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "amoral %s" msgid_plural "amoral %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "amoral %s" +msgstr[1] "amorales %s" +msgstr[2] "amorales %s" #. ~ Description for {'str': 'aspic'} #: data/json/items/comestibles/meat_dishes.json @@ -84102,9 +84392,9 @@ msgstr[2] "fiambres" #, c-format msgid "loathsome %s" msgid_plural "loathsome %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "asqueroso %s" +msgstr[1] "asquerosos %s" +msgstr[2] "asquerosos %s" #. ~ Description for lunch meat #: data/json/items/comestibles/meat_dishes.json @@ -84118,18 +84408,18 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "bologna" msgid_plural "bologna" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bologna" +msgstr[1] "bologna" +msgstr[2] "bologna" #. ~ Conditional name for {'str_sp': 'bologna'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "brat %s" msgid_plural "brat %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pibe %s" +msgstr[1] "pibes %s" +msgstr[2] "pibes %s" #. ~ Conditional name for {'str_sp': 'bologna'} when COMPONENT_ID matches #. mutant @@ -84137,9 +84427,9 @@ msgstr[2] "" #, c-format msgid "bleak %s" msgid_plural "bleak %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lúgubre %s" +msgstr[1] "lúgubres %s" +msgstr[2] "lúgubres %s" #. ~ Description for {'str_sp': 'bologna'} #: data/json/items/comestibles/meat_dishes.json @@ -84173,9 +84463,9 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "SPAM" msgid_plural "SPAM" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Viandada" +msgstr[1] "Viandada" +msgstr[2] "Viandada" #. ~ Description for {'str_sp': 'SPAM'} #: data/json/items/comestibles/meat_dishes.json @@ -84191,9 +84481,9 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "holy SPAM of debugging" msgid_plural "holy SPAMs of debugging" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "santa Viandada del debugging" +msgstr[1] "santas Viandadas del debugging" +msgstr[2] "santas Viandadas del debugging" #. ~ Description for {'str': 'holy SPAM of debugging', 'str_pl': 'holy SPAMs #. of debugging'} @@ -84239,9 +84529,9 @@ msgstr[2] "salsas espesas de Mannwurst" #, c-format msgid "ghastly %s" msgid_plural "ghastly %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "horroroso %s" +msgstr[1] "horrorosos %s" +msgstr[2] "horrorosos %s" #. ~ Description for {'str': 'sausage gravy', 'str_pl': 'sausage gravies'} #: data/json/items/comestibles/meat_dishes.json @@ -84255,18 +84545,18 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "pemmican" msgid_plural "pemmican" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pemmican" +msgstr[1] "pemmican" +msgstr[2] "pemmican" #. ~ Conditional name for {'str_sp': 'pemmican'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "prepper %s" msgid_plural "prepper %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "survivalista %s" +msgstr[1] "survivalistas %s" +msgstr[2] "survivalistas %s" #. ~ Conditional name for {'str_sp': 'pemmican'} when COMPONENT_ID matches #. mutant @@ -84274,9 +84564,9 @@ msgstr[2] "" #, c-format msgid "pernicious %s" msgid_plural "pernicious %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pernicioso %s" +msgstr[1] "perniciosos %s" +msgstr[2] "perniciosos %s" #. ~ Description for {'str_sp': 'pemmican'} #: data/json/items/comestibles/meat_dishes.json @@ -84309,9 +84599,9 @@ msgstr[2] "pastas instantáneas sabor vagabundo" #, c-format msgid "heinous %s" msgid_plural "heinous %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cruel %s" +msgstr[1] "crueles %s" +msgstr[2] "crueles %s" #. ~ Description for hamburger helper #: data/json/items/comestibles/meat_dishes.json @@ -84348,18 +84638,18 @@ msgstr[2] "chilis con carne" #: data/json/items/comestibles/meat_dishes.json msgid "chili con cabron" msgid_plural "chilis con cabron" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chili con cabrón" +msgstr[1] "chilis con cabrón" +msgstr[2] "chilis con cabrón" #. ~ Conditional name for {'str': 'chili con carne', 'str_pl': 'chilis con #. carne'} when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json msgid "chili con chupacabra" msgid_plural "chilis con chupacabra" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chili con chupacabra" +msgstr[1] "chilis con chupacabra" +msgstr[2] "chilis con chupacabra" #. ~ Description for {'str': 'chili con carne', 'str_pl': 'chilis con carne'} #: data/json/items/comestibles/meat_dishes.json @@ -84397,9 +84687,9 @@ msgstr "¡Ahora con el 95 por ciento menos de delfines!" #: data/json/items/comestibles/meat_dishes.json msgid "canned salmon" msgid_plural "canned salmon" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lata de salmón" +msgstr[1] "latas de salmón" +msgstr[2] "latas de salmón" #. ~ Description for {'str_sp': 'canned salmon'} #: data/json/items/comestibles/meat_dishes.json @@ -84421,9 +84711,9 @@ msgstr "Una pasta de pollo blanca y brillante." #: data/json/items/comestibles/meat_dishes.json msgid "pickled herring" msgid_plural "pickled herring" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arenque al escabeche" +msgstr[1] "arenque al escabeche" +msgstr[2] "arenque al escabeche" #. ~ Description for {'str_sp': 'pickled herring'} #: data/json/items/comestibles/meat_dishes.json @@ -84454,17 +84744,17 @@ msgstr[2] "cremas de almejas" #: data/json/items/comestibles/meat_dishes.json msgid "meat chowder" msgid_plural "meat chowders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "crema de carne" +msgstr[1] "cremas de carne" +msgstr[2] "cremas de carne" #. ~ Conditional name for clam chowder when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json msgid "monster chowder" msgid_plural "monster chowders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "crema de monstruo" +msgstr[1] "cremas de monstruo" +msgstr[2] "cremas de monstruo" #. ~ Description for clam chowder #: data/json/items/comestibles/meat_dishes.json @@ -84487,9 +84777,9 @@ msgstr[2] "alubias horneadas" #: data/json/items/comestibles/meat_dishes.json msgid "ork and beans" msgid_plural "ork and beans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "porco con porotos" +msgstr[1] "porco con porotos" +msgstr[2] "porco con porotos" #. ~ Description for {'str_sp': 'baked beans'} #: data/json/items/comestibles/meat_dishes.json @@ -84508,9 +84798,9 @@ msgstr[2] "arroces fritos con carne" #: data/json/items/comestibles/meat_dishes.json msgid "mutant fried rice" msgid_plural "mutant fried rice" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arroz frito con carne mutante" +msgstr[1] "arroz frito con carne mutante" +msgstr[2] "arroz frito con carne mutante" #. ~ Description for {'str_sp': 'meat fried rice'} #: data/json/items/comestibles/meat_dishes.json @@ -84529,9 +84819,9 @@ msgstr[2] "alubias con arroz deluxe" #: data/json/items/comestibles/meat_dishes.json msgid "\"deluxe\" beans and rice" msgid_plural "\"deluxe\" beans and rice" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "porotos con arroz \"deluxe\"" +msgstr[1] "porotos con arroz \"deluxe\"" +msgstr[2] "porotos con arroz \"deluxe\"" #. ~ Description for {'str_sp': 'deluxe beans and rice'} #: data/json/items/comestibles/meat_dishes.json @@ -84553,18 +84843,18 @@ msgstr[2] "tartas de carne" #: data/json/items/comestibles/meat_dishes.json msgid "prick pie" msgid_plural "prick pies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tarta de boludo" +msgstr[1] "tartas de boludo" +msgstr[2] "tartas de boludo" #. ~ Conditional name for meat pie when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "malignant %s" msgid_plural "malignant %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "malicioso %s" +msgstr[1] "maliciosos %s" +msgstr[2] "maliciosos %s" #. ~ Description for meat pie #: data/json/items/comestibles/meat_dishes.json @@ -84582,18 +84872,18 @@ msgstr[2] "pizzas de carne" #: data/json/items/comestibles/meat_dishes.json msgid "poser pizza" msgid_plural "poser pizzas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pizza de impostor" +msgstr[1] "pizzas de impostor" +msgstr[2] "pizzas de impostor" #. ~ Conditional name for meat pizza when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "miserable %s" msgid_plural "miserable %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "miserable %s" +msgstr[1] "miserables %s" +msgstr[2] "miserables %s" #. ~ Description for meat pizza #: data/json/items/comestibles/meat_dishes.json @@ -84607,9 +84897,9 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "supreme pizza" msgid_plural "supreme pizzas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pizza suprema" +msgstr[1] "pizzas supremas" +msgstr[2] "pizzas supremas" #. ~ Description for supreme pizza #: data/json/items/comestibles/meat_dishes.json @@ -84628,9 +84918,9 @@ msgstr[2] "huevos revueltos deluxe" #: data/json/items/comestibles/meat_dishes.json msgid "\"deluxe\" scrambled eggs" msgid_plural "\"deluxe\" scrambled eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevos revueltos \"deluxe\"" +msgstr[1] "huevos revueltos \"deluxe\"" +msgstr[2] "huevos revueltos \"deluxe\"" #. ~ Description for {'str_sp': 'deluxe scrambled eggs'} #: data/json/items/comestibles/meat_dishes.json @@ -84676,9 +84966,9 @@ msgstr[2] "rebanadas de carne salada" #: data/json/items/comestibles/meat_dishes.json msgid "salted simpleton slice" msgid_plural "salted simpleton slices" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "feta de papanatas salada" +msgstr[1] "fetas de papanatas salada" +msgstr[2] "fetas de papanatas salada" #. ~ Description for salted meat slice #: data/json/items/comestibles/meat_dishes.json @@ -84699,9 +84989,9 @@ msgstr[2] "espagueti a la boloñesa" #: data/json/items/comestibles/meat_dishes.json msgid "scoundrel spaghetti" msgid_plural "scoundrel spaghettis" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espagueti a la sinvergüenza" +msgstr[1] "espagueti a la sinvergüenza" +msgstr[2] "espagueti a la sinvergüenza" #. ~ Conditional name for {'str_sp': 'spaghetti bolognese'} when COMPONENT_ID #. matches mutant @@ -84709,9 +84999,9 @@ msgstr[2] "" #, c-format msgid "gnarly %s" msgid_plural "gnarly %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nudoso %s" +msgstr[1] "nudosos %s" +msgstr[2] "nudosos %s" #. ~ Description for {'str_sp': 'spaghetti bolognese'} #: data/json/items/comestibles/meat_dishes.json @@ -84730,18 +85020,18 @@ msgstr[2] "lasañas" #, c-format msgid "Luigi %s" msgid_plural "Luigi %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Luigi %s" +msgstr[1] "Luigi %s" +msgstr[2] "Luigi %s" #. ~ Conditional name for lasagne when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "monster %s" msgid_plural "monster %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "monstruoso %s" +msgstr[1] "monstruosos %s" +msgstr[2] "monstruosos %s" #. ~ Description for lasagne #: data/json/items/comestibles/meat_dishes.json @@ -84755,9 +85045,9 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "fried SPAM" msgid_plural "fried SPAM" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Viandada frita" +msgstr[1] "Viandada frita" +msgstr[2] "Viandada frita" #. ~ Description for {'str_sp': 'fried SPAM'} #: data/json/items/comestibles/meat_dishes.json @@ -84776,18 +85066,18 @@ msgstr[2] "hamburguesas de queso" #, c-format msgid "chump %s" msgid_plural "chump %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tonto %s" +msgstr[1] "tontos %s" +msgstr[2] "tontos %s" #. ~ Conditional name for cheeseburger when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "chilling %s" msgid_plural "chilling %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "escalofriante %s" +msgstr[1] "escalofriantes %s" +msgstr[2] "escalofriantes %s" #. ~ Description for cheeseburger #: data/json/items/comestibles/meat_dishes.json @@ -84809,18 +85099,18 @@ msgstr[2] "hamburguesas" #: data/json/items/comestibles/meat_dishes.json msgid "bobburger" msgid_plural "bobburgers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "juanburguesa" +msgstr[1] "juanburguesas" +msgstr[2] "juanburguesas" #. ~ Conditional name for hamburger when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "horrible %s" msgid_plural "horrible %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "horrible %s" +msgstr[1] "horribles %s" +msgstr[2] "horribles %s" #. ~ Description for hamburger #: data/json/items/comestibles/meat_dishes.json @@ -84830,9 +85120,9 @@ msgstr "Un sandwich de carne picada con condimentos." #: data/json/items/comestibles/meat_dishes.json msgid "sloppy joe" msgid_plural "sloppy joes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sloppy joe" +msgstr[1] "sloppy joes" +msgstr[2] "sloppy joes" #. ~ Conditional name for sloppy joe when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json @@ -84847,9 +85137,9 @@ msgstr[2] "mánguches" #, c-format msgid "suspicious %s" msgid_plural "suspicious %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sospechoso %s" +msgstr[1] "sospechosos %s" +msgstr[2] "sospechosos %s" #. ~ Description for sloppy joe #: data/json/items/comestibles/meat_dishes.json @@ -84872,18 +85162,18 @@ msgstr[2] "tacos" #, c-format msgid "tio %s" msgid_plural "tio %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tío %s" +msgstr[1] "tíos %s" +msgstr[2] "tíos %s" #. ~ Conditional name for taco when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "terrifying %s" msgid_plural "terrifying %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aterrador %s" +msgstr[1] "aterradores %s" +msgstr[2] "aterradores %s" #. ~ Description for taco #: data/json/items/comestibles/meat_dishes.json @@ -84905,9 +85195,9 @@ msgstr[2] "carnes en escabeche" #: data/json/items/comestibles/meat_dishes.json msgid "pickled punk" msgid_plural "pickled punks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "punk al escabeche" +msgstr[1] "punks al escabeche" +msgstr[2] "punks al escabeche" #. ~ Description for pickled meat #: data/json/items/comestibles/meat_dishes.json @@ -84928,9 +85218,9 @@ msgstr[2] "carnes deshidratadas" #, c-format msgid "%s, human" msgid_plural "%s, human" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "%s, humano" +msgstr[1] "%s, humanos" +msgstr[2] "%s, humanos" #. ~ Description for dehydrated meat #: data/json/items/comestibles/meat_dishes.json @@ -84958,9 +85248,9 @@ msgstr "Son trozos de carne rehidratados. Así se disfrutan mucho más." #: data/json/items/comestibles/meat_dishes.json msgid "haggis" msgid_plural "haggises" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "haggis" +msgstr[1] "haggises" +msgstr[2] "haggises" #. ~ Conditional name for {'str': 'haggis', 'str_pl': 'haggises'} when FLAG #. matches CANNIBALISM @@ -84970,9 +85260,9 @@ msgstr[2] "" #, c-format msgid "human %s" msgid_plural "human %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "humano %s" +msgstr[1] "humanos %s" +msgstr[2] "humanos %s" #. ~ Description for {'str': 'haggis', 'str_pl': 'haggises'} #: data/json/items/comestibles/meat_dishes.json @@ -85016,9 +85306,9 @@ msgstr[2] "temaki de carne" #, c-format msgid "troubling %s" msgid_plural "troubling %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "inquietante %s" +msgstr[1] "inquietantes %s" +msgstr[2] "inquietantes %s" #. ~ Description for {'str_sp': 'meat temaki'} #: data/json/items/comestibles/meat_dishes.json @@ -85069,9 +85359,9 @@ msgstr[2] "pelmenis" #, c-format msgid "perilous %s" msgid_plural "perilous %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arriesgado %s" +msgstr[1] "arriesgados %s" +msgstr[2] "arriesgados %s" #. ~ Description for pelmeni #: data/json/items/comestibles/meat_dishes.json @@ -85085,17 +85375,17 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "homemade burrito" msgid_plural "homemade burritos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "burrito casero" +msgstr[1] "burritos caseros" +msgstr[2] "burritos caseros" #. ~ Conditional name for homemade burrito when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json msgid "bone-chilling burrito" msgid_plural "bone-chilling burritos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "burrito espeluznante" +msgstr[1] "burritos espeluznantes" +msgstr[2] "burritos espeluznantes" #. ~ Description for homemade burrito #: data/json/items/comestibles/meat_dishes.json @@ -85129,9 +85419,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "melatonin tablet" msgid_plural "melatonin tablets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pastilla de melatonina" +msgstr[1] "pastillas de melatonina" +msgstr[2] "pastillas de melatonina" #. ~ Use action activation_message for melatonin tablet. #: data/json/items/comestibles/med.json @@ -85195,9 +85485,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "antibiotics" msgid_plural "antibiotics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "antibióticos" +msgstr[1] "antibióticos" +msgstr[2] "antibióticos" #. ~ Description for {'str_sp': 'antibiotics'} #: data/json/items/comestibles/med.json @@ -85229,9 +85519,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "antiparasitic drug" msgid_plural "antiparasitic drug" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "droga antiparasitaria" +msgstr[1] "droga antiparasitaria" +msgstr[2] "droga antiparasitaria" #. ~ Description for {'str_sp': 'antiparasitic drug'} #: data/json/items/comestibles/med.json @@ -85280,9 +85570,9 @@ msgstr "Son vendas comunes de tela. Se usan para curar lastimaduras pequeñas." #: data/json/items/comestibles/med.json msgid "makeshift bandage" msgid_plural "makeshift bandages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "venda improvisada" +msgstr[1] "vendas improvisadas" +msgstr[2] "vendas improvisadas" #. ~ Description for makeshift bandage #: data/json/items/comestibles/med.json @@ -85292,9 +85582,9 @@ msgstr "Es un venda común de tela. Mejor que nada." #: data/json/items/comestibles/med.json msgid "bleached makeshift bandage" msgid_plural "bleached makeshift bandages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "venda improvisada con lavandina" +msgstr[1] "vendas improvisadas con lavandina" +msgstr[2] "vendas improvisadas con lavandina" #. ~ Description for {'str': 'bleached makeshift bandage'} #: data/json/items/comestibles/med.json @@ -85304,9 +85594,9 @@ msgstr "Es una venda común de tela. Es blanca... como las vendas de en serio." #: data/json/items/comestibles/med.json msgid "boiled makeshift bandage" msgid_plural "boiled makeshift bandages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "venda improvisada hervida" +msgstr[1] "vendas improvisadas hervidas" +msgstr[2] "vendas improvisadas hervidas" #. ~ Description for {'str': 'boiled makeshift bandage'} #: data/json/items/comestibles/med.json @@ -85422,9 +85712,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "chloroform soaked rag" msgid_plural "chloroform soaked rags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trapo empapado con cloroformo" +msgstr[1] "trapos empapados con cloroformo" +msgstr[2] "trapos empapados con cloroformo" #. ~ Description for chloroform soaked rag #: data/json/items/comestibles/med.json @@ -85572,9 +85862,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "antiseptic" msgid_plural "antiseptic" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "antiséptico" +msgstr[1] "antiséptico" +msgstr[2] "antiséptico" #. ~ Description for {'str_sp': 'antiseptic'} #: data/json/items/comestibles/med.json @@ -85584,9 +85874,9 @@ msgstr "Un poderoso antiséptico comúnmente usado para heridas contaminadas." #: data/json/items/comestibles/med.json msgid "makeshift antiseptic" msgid_plural "makeshift antiseptics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "antiséptico improvisado" +msgstr[1] "antisépticos improvisados" +msgstr[2] "antisépticos improvisados" #. ~ Description for makeshift antiseptic #: data/json/items/comestibles/med.json @@ -85902,6 +86192,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "chicle" @@ -85958,9 +86249,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "potassium iodide tablet" msgid_plural "potassium iodide tablets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pastilla de yoduro de potasio" +msgstr[1] "pastillas de yoduro de potasio" +msgstr[2] "pastillas de yoduro de potasio" #. ~ Use action activation_message for potassium iodide tablet. #: data/json/items/comestibles/med.json @@ -85988,9 +86279,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "pink tab" msgid_plural "pink tabs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartoncito rosa" +msgstr[1] "cartoncitos rosas" +msgstr[2] "cartoncitos rosas" #. ~ Use action activation_message for pink tab. #: data/json/items/comestibles/med.json @@ -86065,9 +86356,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "mugwort oil" msgid_plural "mugwort oils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aceite de abrótano" +msgstr[1] "aceites de abrótano" +msgstr[2] "aceites de abrótano" #. ~ Description for mugwort oil #: data/json/items/comestibles/med.json @@ -86114,9 +86405,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "oxycodone" msgid_plural "oxycodones" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "oxicodona" +msgstr[1] "oxicodonas" +msgstr[2] "oxicodonas" #. ~ Use action activation_message for oxycodone. #: data/json/items/comestibles/med.json @@ -86135,9 +86426,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "Ambien" msgid_plural "Ambien" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Ambien" +msgstr[1] "Ambien" +msgstr[2] "Ambien" #. ~ Description for {'str_sp': 'Ambien'} #: data/json/items/comestibles/med.json @@ -86203,9 +86494,9 @@ msgstr "Jarabe para la tos hecho de amapola mutada. Te va a dar sueño." #: data/json/items/comestibles/med.json msgid "Prozac" msgid_plural "Prozac" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Prozac" +msgstr[1] "Prozac" +msgstr[2] "Prozac" #. ~ Description for {'str_sp': 'Prozac'} #: data/json/items/comestibles/med.json @@ -86223,9 +86514,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "Prussian blue tablet" msgid_plural "Prussian blue tablets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pastilla de azul de Prusia" +msgstr[1] "pastillas de azul de Prusia" +msgstr[2] "pastillas de azul de Prusia" #. ~ Use action activation_message for {'str': 'Prussian blue tablet'}. #: data/json/items/comestibles/med.json @@ -86278,9 +86569,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "Thorazine" msgid_plural "Thorazine" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Torazina" +msgstr[1] "Torazina" +msgstr[2] "Torazina" #. ~ Description for {'str_sp': 'Thorazine'} #: data/json/items/comestibles/med.json @@ -86296,9 +86587,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "thyme oil" msgid_plural "thyme oils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aceite de tomillo" +msgstr[1] "aceites de tomillo" +msgstr[2] "aceites de tomillo" #. ~ Description for thyme oil #: data/json/items/comestibles/med.json @@ -86355,9 +86646,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "gamma globulin shot" msgid_plural "gamma globulin shots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vacuna de gamma globulina" +msgstr[1] "vacunas de gamma globulina" +msgstr[2] "vacunas de gamma globulina" #. ~ Description for gamma globulin shot #: data/json/items/comestibles/med.json @@ -86373,9 +86664,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "multivitamin" msgid_plural "multivitamins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "multivitaminas" +msgstr[1] "multivitaminas" +msgstr[2] "multivitaminas" #. ~ Use action activation_message for multivitamin. #. ~ Use action activation_message for calcium tablet. @@ -86399,9 +86690,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "calcium tablet" msgid_plural "calcium tablets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pastilla de calcio" +msgstr[1] "pastillas de calcio" +msgstr[2] "pastillas de calcio" #. ~ Description for calcium tablet #: data/json/items/comestibles/med.json @@ -86416,9 +86707,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "bone meal tablet" msgid_plural "bone meal tablets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pastilla de harina de hueso" +msgstr[1] "pastillas de harina de hueso" +msgstr[2] "pastillas de harina de hueso" #. ~ Description for bone meal tablet #: data/json/items/comestibles/med.json @@ -86432,9 +86723,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "flavored bone meal tablet" msgid_plural "flavored bone meal tablets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pastilla de harina de hueso con sabor" +msgstr[1] "pastillas de harina de hueso con sabor" +msgstr[2] "pastillas de harina de hueso con sabor" #. ~ Description for flavored bone meal tablet #: data/json/items/comestibles/med.json @@ -86469,9 +86760,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "injectable vitamin B" msgid_plural "injectable vitamin Bs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vitamina B inyectable" +msgstr[1] "vitamina B inyectable" +msgstr[2] "vitamina B inyectable" #. ~ Use action activation_message for injectable vitamin B. #: data/json/items/comestibles/med.json @@ -86490,9 +86781,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "injectable iron" msgid_plural "injectable irons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hierro inyectable" +msgstr[1] "hierro inyectable" +msgstr[2] "hierro inyectable" #. ~ Use action activation_message for injectable iron. #: data/json/items/comestibles/med.json @@ -86545,9 +86836,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "antiseptic soaked rag" msgid_plural "antiseptic soaked rags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trapo empapado de antiséptico" +msgstr[1] "trapos empapados de antiséptico" +msgstr[2] "trapos empapados de antiséptico" #. ~ Description for {'str': 'antiseptic soaked rag'} #: data/json/items/comestibles/med.json @@ -86561,9 +86852,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "antiseptic soaked cotton balls" msgid_plural "antiseptic soaked cotton balls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "algodón empapado de antiséptico" +msgstr[1] "algodón empapado de antiséptico" +msgstr[2] "algodón empapado de antiséptico" #. ~ Description for {'str_sp': 'antiseptic soaked cotton balls'} #: data/json/items/comestibles/med.json @@ -86596,9 +86887,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "heartburn medicine" msgid_plural "heartburn medicines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "antiácido" +msgstr[1] "antiácidos" +msgstr[2] "antiácidos" #. ~ Use action activation_message for heartburn medicine. #: data/json/items/comestibles/med.json @@ -86619,9 +86910,9 @@ msgstr "" #: data/mods/Aftershock/items/comestibles/comestibles.json msgid "Panaceus" msgid_plural "Panaceii" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Panacea" +msgstr[1] "Panaceas" +msgstr[2] "Panaceas" #. ~ Use action activation_message for {'str': 'Panaceus', 'str_pl': #. 'Panaceii'}. @@ -86648,9 +86939,9 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "cattail jelly" msgid_plural "cattail jellies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gelatina de junco" +msgstr[1] "gelatinas de junco" +msgstr[2] "gelatinas de junco" #. ~ Description for {'str': 'cattail jelly', 'str_pl': 'cattail jellies'} #: data/json/items/comestibles/med.json @@ -86708,9 +86999,9 @@ msgstr "Una caja pequeña MRE, no deberías ver esto." #: data/json/items/comestibles/mre.json msgid "MRE entree" msgid_plural "MRE entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE entrada" +msgstr[1] "MRE entrada" +msgstr[2] "MRE entrada" #. ~ Description for {'str': 'MRE entree'} #: data/json/items/comestibles/mre.json @@ -86774,9 +87065,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - BBQ Beef" msgid_plural "MREs - BBQ Beef" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Parrillada de vaca" +msgstr[1] "MREs - Parrillada de vaca" +msgstr[2] "MREs - Parrillada de vaca" #. ~ Description for {'str': 'MRE - BBQ Beef', 'str_pl': 'MREs - BBQ Beef'} #: data/json/items/comestibles/mre.json @@ -86832,9 +87123,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chicken Chunks" msgid_plural "MREs - Chicken Chunks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Pollo Trozado" +msgstr[1] "MREs - Pollo Trozado" +msgstr[2] "MREs - Pollo Trozado" #. ~ Description for {'str': 'MRE - Chicken Chunks', 'str_pl': 'MREs - Chicken #. Chunks'} @@ -86852,9 +87143,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Beef Taco" msgid_plural "MREs - Beef Taco" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Taco de Carne" +msgstr[1] "MREs - Taco de Carne" +msgstr[2] "MREs - Taco de Carne" #. ~ Description for {'str': 'MRE - Beef Taco', 'str_pl': 'MREs - Beef Taco'} #: data/json/items/comestibles/mre.json @@ -86871,9 +87162,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Beef Brisket" msgid_plural "MREs - Beef Brisket" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Costilla de Vaca" +msgstr[1] "MREs - Costilla de Vaca" +msgstr[2] "MREs - Costilla de Vaca" #. ~ Description for {'str': 'MRE - Beef Brisket', 'str_pl': 'MREs - Beef #. Brisket'} @@ -86891,9 +87182,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Meatballs & Marinara" msgid_plural "MREs - Meatballs & Marinara" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Albóndigas con marinera" +msgstr[1] "MREs - Albóndigas con marinera" +msgstr[2] "MREs - Albóndigas con marinera" #. ~ Description for {'str': 'MRE - Meatballs & Marinara', 'str_pl': 'MREs - #. Meatballs & Marinara'} @@ -86930,9 +87221,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chili & Macaroni" msgid_plural "MREs - Chili & Macaroni" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Macarrones con chili" +msgstr[1] "MREs - Macarrones con chili" +msgstr[2] "MREs - Macarrones con chili" #. ~ Description for {'str': 'MRE - Chili & Macaroni', 'str_pl': 'MREs - Chili #. & Macaroni'} @@ -86970,9 +87261,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Macaroni Marinara" msgid_plural "MREs - Macaroni Marinara" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Macarrones con Marinera" +msgstr[1] "MREs - Macarrones con Marinera" +msgstr[2] "MREs - Macarrones con Marinera" #. ~ Description for {'str': 'MRE - Macaroni Marinara', 'str_pl': 'MREs - #. Macaroni Marinara'} @@ -86990,9 +87281,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Cheese Tortellini" msgid_plural "MREs - Cheese Tortellini" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Capelettini de Queso" +msgstr[1] "MREs - Capelettini de Queso" +msgstr[2] "MREs - Capelettini de Queso" #. ~ Description for {'str': 'MRE - Cheese Tortellini', 'str_pl': 'MREs - #. Cheese Tortellini'} @@ -87030,9 +87321,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Mexican Chicken Stew" msgid_plural "MREs - Mexican Chicken Stew" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Estofado Mexicano de Pollo" +msgstr[1] "MREs - Estofado Mexicano de Pollo" +msgstr[2] "MREs - Estofado Mexicano de Pollo" #. ~ Description for {'str': 'MRE - Mexican Chicken Stew', 'str_pl': 'MREs - #. Mexican Chicken Stew'} @@ -87050,9 +87341,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chicken Burrito Bowl" msgid_plural "MREs - Chicken Burrito Bowl" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Burrito de Pollo" +msgstr[1] "MREs - Burrito de Pollo" +msgstr[2] "MREs - Burrito de Pollo" #. ~ Description for {'str': 'MRE - Chicken Burrito Bowl', 'str_pl': 'MREs - #. Chicken Burrito Bowl'} @@ -87109,9 +87400,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Pepper Jack Beef" msgid_plural "MREs - Pepper Jack Beef" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Carne con Queso Jack" +msgstr[1] "MREs - Carne con Queso Jack" +msgstr[2] "MREs - Carne con Queso Jack" #. ~ Description for {'str': 'MRE - Pepper Jack Beef', 'str_pl': 'MREs - #. Pepper Jack Beef'} @@ -87129,9 +87420,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Hash Browns & Bacon" msgid_plural "MREs - Hash Browns & Bacon" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Hash Browns y Panceta" +msgstr[1] "MREs - Hash Browns y Panceta" +msgstr[2] "MREs - Hash Browns y Panceta" #. ~ Description for {'str': 'MRE - Hash Browns & Bacon', 'str_pl': 'MREs - #. Hash Browns & Bacon'} @@ -87169,9 +87460,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Asian Beef & Vegetables" msgid_plural "MREs - Asian Beef & Vegetables" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Carne de Asia con Verduras" +msgstr[1] "MREs - Carne de Asia con Verduras" +msgstr[2] "MREs - Carne de Asia con Verduras" #. ~ Description for {'str': 'MRE - Asian Beef & Vegetables', 'str_pl': 'MREs #. - Asian Beef & Vegetables'} @@ -87189,9 +87480,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chicken Pesto & Pasta" msgid_plural "MREs - Chicken Pesto & Pasta" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Pasta con Pesto y Pollo" +msgstr[1] "MREs - Pasta con Pesto y Pollo" +msgstr[2] "MREs - Pasta con Pesto y Pollo" #. ~ Description for {'str': 'MRE - Chicken Pesto & Pasta', 'str_pl': 'MREs - #. Chicken Pesto & Pasta'} @@ -87209,9 +87500,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Southwest Beef & Beans" msgid_plural "MREs - Southwest Beef & Beans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Carne del Suroeste con Porotos" +msgstr[1] "MREs - Carne del Suroeste con Porotos" +msgstr[2] "MREs - Carne del Suroeste con Porotos" #. ~ Description for {'str': 'MRE - Southwest Beef & Beans', 'str_pl': 'MREs - #. Southwest Beef & Beans'} @@ -87229,9 +87520,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Frankfurters & Beans" msgid_plural "MREs - Frankfurters & Beans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MRE - Salchichas de Frankfurt con porotos" +msgstr[1] "MREs - Salchichas de Frankfurt con porotos" +msgstr[2] "MREs - Salchichas de Frankfurt con porotos" #. ~ Description for {'str': 'MRE - Frankfurters & Beans', 'str_pl': 'MREs - #. Frankfurters & Beans'} @@ -87248,9 +87539,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "chili & beans entree" msgid_plural "chili & beans entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de porotos con chili" +msgstr[1] "entradas de porotos con chili" +msgstr[2] "entradas de porotos con chili" #. ~ Description for chili & beans entree #: data/json/items/comestibles/mre.json @@ -87265,9 +87556,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "BBQ beef entree" msgid_plural "BBQ beef entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de parrillada de vaca" +msgstr[1] "entradas de parrillada de vaca" +msgstr[2] "entradas de parrillada de vaca" #. ~ Description for {'str': 'BBQ beef entree'} #: data/json/items/comestibles/mre.json @@ -87282,9 +87573,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "chicken noodle entree" msgid_plural "chicken noodle entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de pollo y fideos" +msgstr[1] "entradas de pollo y fideos" +msgstr[2] "entradas de pollo y fideos" #. ~ Description for chicken noodle entree #: data/json/items/comestibles/mre.json @@ -87299,9 +87590,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "spaghetti entree" msgid_plural "spaghetti entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de espagueti" +msgstr[1] "entradas de espagueti" +msgstr[2] "entradas de espagueti" #. ~ Description for spaghetti entree #: data/json/items/comestibles/mre.json @@ -87316,9 +87607,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "chicken chunks entree" msgid_plural "chicken chunks entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de pollo trozado" +msgstr[1] "entradas de pollo trozado" +msgstr[2] "entradas de pollo trozado" #. ~ Description for chicken chunks entree #: data/json/items/comestibles/mre.json @@ -87333,9 +87624,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "beef taco entree" msgid_plural "beef taco entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de taco de carne" +msgstr[1] "entradas de taco de carne" +msgstr[2] "entradas de taco de carne" #. ~ Description for {'str': 'beef taco entree'} #: data/json/items/comestibles/mre.json @@ -87350,9 +87641,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "beef brisket entree" msgid_plural "beef brisket entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de costilla de vaca" +msgstr[1] "entradas de costilla de vaca" +msgstr[2] "entradas de costilla de vaca" #. ~ Description for {'str': 'beef brisket entree'} #: data/json/items/comestibles/mre.json @@ -87367,9 +87658,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "meatballs & marinara entree" msgid_plural "meatballs & marinara entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de albóndigas con marinera" +msgstr[1] "entradas de albóndigas con marinera" +msgstr[2] "entradas de albóndigas con marinera" #. ~ Description for meatballs & marinara entree #: data/json/items/comestibles/mre.json @@ -87384,9 +87675,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "beef stew entree" msgid_plural "beef stew entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de estofado de carne" +msgstr[1] "entradas de estofado de carne" +msgstr[2] "entradas de estofado de carne" #. ~ Description for {'str': 'beef stew entree'} #: data/json/items/comestibles/mre.json @@ -87401,9 +87692,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "chili & macaroni entree" msgid_plural "chili & macaroni entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de macarrones con chili" +msgstr[1] "entradas de macarrones con chili" +msgstr[2] "entradas de macarrones con chili" #. ~ Description for chili & macaroni entree #: data/json/items/comestibles/mre.json @@ -87418,9 +87709,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "vegetarian taco entree" msgid_plural "vegetarian taco entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de taco vegetariano" +msgstr[1] "entradas de taco vegetariano" +msgstr[2] "entradas de taco vegetariano" #. ~ Description for vegetarian taco entree #: data/json/items/comestibles/mre.json @@ -87435,9 +87726,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "macaroni & marinara entree" msgid_plural "macaroni & marinara entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de macarrones con marinera" +msgstr[1] "entradas de macarrones con marinera" +msgstr[2] "entradas de macarrones con marinera" #. ~ Description for macaroni & marinara entree #: data/json/items/comestibles/mre.json @@ -87452,9 +87743,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "cheese tortellini entree" msgid_plural "cheese tortellini entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de capelettini de queso" +msgstr[1] "entradas de capelettini de queso" +msgstr[2] "entradas de capelettini de queso" #. ~ Description for cheese tortellini entree #: data/json/items/comestibles/mre.json @@ -87469,9 +87760,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "mushroom fettuccine entree" msgid_plural "mushroom fettuccine entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de fetuchini con champiñones" +msgstr[1] "entradas de fetuchini con champiñones" +msgstr[2] "entradas de fetuchini con champiñones" #. ~ Description for mushroom fettuccine entree #: data/json/items/comestibles/mre.json @@ -87486,9 +87777,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "Mexican chicken stew entree" msgid_plural "Mexican chicken stew entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de estofado mexicano de pollo" +msgstr[1] "entradas de estofado mexicano de pollo" +msgstr[2] "entradas de estofado mexicano de pollo" #. ~ Description for {'str': 'Mexican chicken stew entree'} #: data/json/items/comestibles/mre.json @@ -87503,9 +87794,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "chicken burrito bowl entree" msgid_plural "chicken burrito bowl entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de burrito de pollo" +msgstr[1] "entradas de burrito de pollo" +msgstr[2] "entradas de burrito de pollo" #. ~ Description for chicken burrito bowl entree #: data/json/items/comestibles/mre.json @@ -87520,9 +87811,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "maple sausage entree" msgid_plural "maple sausage entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de salchicha de arce" +msgstr[1] "entradas de salchicha de arce" +msgstr[2] "entradas de salchicha de arce" #. ~ Description for maple sausage entree #: data/json/items/comestibles/mre.json @@ -87537,9 +87828,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "ravioli entree" msgid_plural "ravioli entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de ravioles" +msgstr[1] "entradas de ravioles" +msgstr[2] "entradas de ravioles" #. ~ Description for ravioli entree #: data/json/items/comestibles/mre.json @@ -87554,9 +87845,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "pepper jack beef entree" msgid_plural "pepper jack beef entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de carne con queso Jack" +msgstr[1] "entradas de carne con queso Jack" +msgstr[2] "entradas de carne con queso Jack" #. ~ Description for pepper jack beef entree #: data/json/items/comestibles/mre.json @@ -87571,9 +87862,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "hash browns & bacon entree" msgid_plural "hash browns & bacon entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de hash browns y panceta" +msgstr[1] "entradas de hash browns y panceta" +msgstr[2] "entradas de hash browns y panceta" #. ~ Description for hash browns & bacon entree #: data/json/items/comestibles/mre.json @@ -87588,9 +87879,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "lemon pepper tuna entree" msgid_plural "lemon pepper tuna entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de atún con pimienta y limón" +msgstr[1] "entradas de atún con pimienta y limón" +msgstr[2] "entradas de atún con pimienta y limón" #. ~ Description for lemon pepper tuna entree #: data/json/items/comestibles/mre.json @@ -87605,9 +87896,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "asian beef & vegetables entree" msgid_plural "asian beef & vegetables entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de carne de asia con verduras" +msgstr[1] "entradas de carne de asia con verduras" +msgstr[2] "entradas de carne de asia con verduras" #. ~ Description for {'str': 'asian beef & vegetables entree'} #: data/json/items/comestibles/mre.json @@ -87622,9 +87913,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "chicken pesto & pasta entree" msgid_plural "chicken pesto & pasta entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de pasta con pesto y pollo" +msgstr[1] "entradas de pasta con pesto y pollo" +msgstr[2] "entradas de pasta con pesto y pollo" #. ~ Description for chicken pesto & pasta entree #: data/json/items/comestibles/mre.json @@ -87639,9 +87930,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "southwest beef & beans entree" msgid_plural "southwest beef & beans entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de carne del suroeste con porotos" +msgstr[1] "entradas de carne del suroeste con porotos" +msgstr[2] "entradas de carne del suroeste con porotos" #. ~ Description for southwest beef & beans entree #: data/json/items/comestibles/mre.json @@ -87656,9 +87947,9 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "frankfurters & beans entree" msgid_plural "frankfurters & beans entrees" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "entrada de salchicha de Frankfurt con porotos" +msgstr[1] "entradas de salchicha de Frankfurt con porotos" +msgstr[2] "entradas de salchicha de Frankfurt con porotos" #. ~ Description for frankfurters & beans entree #: data/json/items/comestibles/mre.json @@ -87674,9 +87965,9 @@ msgstr "" #: data/json/items/comestibles/mushroom.json msgid "cooked mushroom" msgid_plural "cooked mushrooms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hongo cocinado" +msgstr[1] "hongos cocinados" +msgstr[2] "hongos cocinados" #. ~ Description for cooked mushroom #: data/json/items/comestibles/mushroom.json @@ -87757,9 +88048,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "abstract mutagen flavor" msgid_plural "abstract mutagen flavors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sabor abstracto de mutágeno" +msgstr[1] "sabores abstractos de mutágeno" +msgstr[2] "sabores abstractos de mutágeno" #. ~ Description for {'str': 'abstract mutagen flavor'} #: data/json/items/comestibles/mutagen.json @@ -87770,9 +88061,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "abstract iv mutagen flavor" msgid_plural "abstract iv mutagen flavors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sabor abstracto de mutágeno iv" +msgstr[1] "sabores abstractos de mutágeno iv" +msgstr[2] "sabores abstractos de mutágeno iv" #. ~ Description for {'str': 'abstract iv mutagen flavor'} #: data/json/items/comestibles/mutagen.json @@ -87793,9 +88084,9 @@ msgstr[2] "sueros mutágeno" #: data/json/items/comestibles/mutagen.json msgid "alpha serum" msgid_plural "alpha serum" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero alfa" +msgstr[1] "suero alfa" +msgstr[2] "suero alfa" #. ~ Description for {'str_sp': 'alpha serum'} #: data/json/items/comestibles/mutagen.json @@ -87858,9 +88149,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "cephalopod serum" msgid_plural "cephalopod serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de cefalópodo" +msgstr[1] "sueros de cefalópodo" +msgstr[2] "sueros de cefalópodo" #. ~ Description for cephalopod serum #: data/json/items/comestibles/mutagen.json @@ -87939,9 +88230,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "insect serum" msgid_plural "insect serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de insecto" +msgstr[1] "sueros de insecto" +msgstr[2] "sueros de insecto" #. ~ Description for insect serum #: data/json/items/comestibles/mutagen.json @@ -87987,9 +88278,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "medical serum" msgid_plural "medical serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero médico" +msgstr[1] "sueros médicos" +msgstr[2] "sueros médicos" #. ~ Description for medical serum #: data/json/items/comestibles/mutagen.json @@ -88052,9 +88343,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "slime serum" msgid_plural "slime serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de slime" +msgstr[1] "sueros de slime" +msgstr[2] "sueros de slime" #. ~ Description for slime serum #: data/json/items/comestibles/mutagen.json @@ -88085,9 +88376,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "troglobite serum" msgid_plural "troglobite serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de troglobio" +msgstr[1] "sueros de troglobio" +msgstr[2] "sueros de troglobio" #. ~ Description for troglobite serum #: data/json/items/comestibles/mutagen.json @@ -88101,9 +88392,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "ursine serum" msgid_plural "ursine serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de osuno" +msgstr[1] "sueros de osuno" +msgstr[2] "sueros de osuno" #. ~ Description for ursine serum #: data/json/items/comestibles/mutagen.json @@ -88117,9 +88408,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "mouse serum" msgid_plural "mouse serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de ratón" +msgstr[1] "sueros de ratón" +msgstr[2] "sueros de ratón" #. ~ Description for mouse serum #: data/json/items/comestibles/mutagen.json @@ -88140,9 +88431,9 @@ msgstr[2] "mutágenos" #: data/json/items/comestibles/mutagen.json msgid "congealed blood" msgid_plural "congealed bloods" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sangre coagulada" +msgstr[1] "sangre coagulada" +msgstr[2] "sangre coagulada" #. ~ Description for congealed blood #: data/json/items/comestibles/mutagen.json @@ -88156,9 +88447,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "alpha mutagen" msgid_plural "alpha mutagen" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno alfa" +msgstr[1] "mutágeno alfa" +msgstr[2] "mutágeno alfa" #. ~ Description for {'str_sp': 'alpha mutagen'} #. ~ Description for chimera mutagen @@ -88213,9 +88504,9 @@ msgstr[2] "mutágenos elf-a" #: data/json/items/comestibles/mutagen.json msgid "feline mutagen" msgid_plural "feline mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de felino" +msgstr[1] "mutágenos de felino" +msgstr[2] "mutágenos de felino" #: data/json/items/comestibles/mutagen.json msgid "fish mutagen" @@ -88262,9 +88553,9 @@ msgstr[2] "mutágenos de plantas" #: data/json/items/comestibles/mutagen.json msgid "raptor mutagen" msgid_plural "raptor mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de raptor" +msgstr[1] "mutágenos de raptor" +msgstr[2] "mutágenos de raptor" #: data/json/items/comestibles/mutagen.json msgid "rat mutagen" @@ -88276,9 +88567,9 @@ msgstr[2] "mutágenos de rata" #: data/json/items/comestibles/mutagen.json msgid "slime mutagen" msgid_plural "slime mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de slime" +msgstr[1] "mutágenos de slime" +msgstr[2] "mutágenos de slime" #: data/json/items/comestibles/mutagen.json msgid "spider mutagen" @@ -88290,9 +88581,9 @@ msgstr[2] "mutágenos de araña" #: data/json/items/comestibles/mutagen.json msgid "troglobite mutagen" msgid_plural "troglobite mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de troglobio" +msgstr[1] "mutágenos de troglobio" +msgstr[2] "mutágenos de troglobio" #: data/json/items/comestibles/mutagen.json msgid "ursine mutagen" @@ -88304,9 +88595,9 @@ msgstr[2] "mutágenos de osuno" #: data/json/items/comestibles/mutagen.json msgid "mouse mutagen" msgid_plural "mouse mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de ratón" +msgstr[1] "mutágenos de ratón" +msgstr[2] "mutágenos de ratón" #: data/json/items/comestibles/mutagen.json msgid "purifier" @@ -88342,9 +88633,9 @@ msgstr "" #: data/json/items/comestibles/mutagen.json msgid "purifier smart shot" msgid_plural "purifier smart shots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dosis de purificante inteligente" +msgstr[1] "dosis de purificante inteligente" +msgstr[2] "dosis de purificante inteligente" #. ~ Description for purifier smart shot #: data/json/items/comestibles/mutagen.json @@ -88446,9 +88737,9 @@ msgstr "Es un puñado de frutos secos sabrosos y crujientes de una piña." #: data/json/items/comestibles/nuts.json msgid "junipers" msgid_plural "junipers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "enebros" +msgstr[1] "enebros" +msgstr[2] "enebros" #. ~ Description for {'str_sp': 'junipers'} #: data/json/items/comestibles/nuts.json @@ -88462,9 +88753,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "pistachios" msgid_plural "pistachios" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pistachos" +msgstr[1] "pistachos" +msgstr[2] "pistachos" #. ~ Description for {'str_sp': 'pistachios'} #: data/json/items/comestibles/nuts.json @@ -88474,9 +88765,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted pistachios" msgid_plural "roasted pistachios" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pistachos tostados" +msgstr[1] "pistachos tostados" +msgstr[2] "pistachos tostados" #. ~ Description for {'str_sp': 'roasted pistachios'} #: data/json/items/comestibles/nuts.json @@ -88486,9 +88777,9 @@ msgstr "Es un puñado de frutos secos tostados del árbol del pistacho." #: data/json/items/comestibles/nuts.json msgid "almonds" msgid_plural "almonds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "almendras" +msgstr[1] "almendras" +msgstr[2] "almendras" #. ~ Description for {'str_sp': 'almonds'} #: data/json/items/comestibles/nuts.json @@ -88498,9 +88789,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "almond pulp" msgid_plural "almond pulp" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulpa de almendra" +msgstr[1] "pulpa de almendra" +msgstr[2] "pulpa de almendra" #. ~ Description for {'str_sp': 'almond pulp'} #: data/json/items/comestibles/nuts.json @@ -88513,9 +88804,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted almonds" msgid_plural "roasted almonds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "almendras tostadas" +msgstr[1] "almendras tostadas" +msgstr[2] "almendras tostadas" #. ~ Description for {'str_sp': 'roasted almonds'} #: data/json/items/comestibles/nuts.json @@ -88525,9 +88816,9 @@ msgstr "Es un puñado de frutos secos tostados del almendro." #: data/json/items/comestibles/nuts.json msgid "cashews" msgid_plural "cashews" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "castañas de cajú" +msgstr[1] "castañas de cajú" +msgstr[2] "castañas de cajú" #. ~ Description for {'str_sp': 'cashews'} #: data/json/items/comestibles/nuts.json @@ -88537,9 +88828,9 @@ msgstr "Es un puñado de castañas de cajú saladas." #: data/json/items/comestibles/nuts.json msgid "pecans" msgid_plural "pecans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nueces de pacana" +msgstr[1] "nueces de pacana" +msgstr[2] "nueces de pacana" #. ~ Description for {'str_sp': 'pecans'} #: data/json/items/comestibles/nuts.json @@ -88549,9 +88840,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted pecans" msgid_plural "roasted pecans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nueces de pacana tostadas" +msgstr[1] "nueces de pacana tostadas" +msgstr[2] "nueces de pacana tostadas" #. ~ Description for {'str_sp': 'roasted pecans'} #: data/json/items/comestibles/nuts.json @@ -88561,9 +88852,9 @@ msgstr "Es un puñado de frutos secos tostados del árbol del pacano." #: data/json/items/comestibles/nuts.json msgid "peanuts" msgid_plural "peanuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maníes" +msgstr[1] "maníes" +msgstr[2] "maníes" #. ~ Description for {'str_sp': 'peanuts'} #: data/json/items/comestibles/nuts.json @@ -88573,9 +88864,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "beech nuts" msgid_plural "beech nuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hayucos" +msgstr[1] "hayucos" +msgstr[2] "hayucos" #. ~ Description for {'str_sp': 'beech nuts'} #: data/json/items/comestibles/nuts.json @@ -88585,9 +88876,9 @@ msgstr "Es un puñado de frutos secos y puntiagudos del haya." #: data/json/items/comestibles/nuts.json msgid "walnuts" msgid_plural "walnuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nueces" +msgstr[1] "nueces" +msgstr[2] "nueces" #. ~ Description for {'str_sp': 'walnuts'} #: data/json/items/comestibles/nuts.json @@ -88597,9 +88888,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted walnuts" msgid_plural "roasted walnuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nueces tostadas" +msgstr[1] "nueces tostadas" +msgstr[2] "nueces tostadas" #. ~ Description for {'str_sp': 'roasted walnuts'} #: data/json/items/comestibles/nuts.json @@ -88609,9 +88900,9 @@ msgstr "Es un puñado de frutos secos tostados del nogal." #: data/json/items/comestibles/nuts.json msgid "chestnuts" msgid_plural "chestnuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "castañas" +msgstr[1] "castañas" +msgstr[2] "castañas" #. ~ Description for {'str_sp': 'chestnuts'} #: data/json/items/comestibles/nuts.json @@ -88621,9 +88912,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted chestnuts" msgid_plural "roasted chestnuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "castañas tostadas" +msgstr[1] "castañas tostadas" +msgstr[2] "castañas tostadas" #. ~ Description for {'str_sp': 'roasted chestnuts'} #: data/json/items/comestibles/nuts.json @@ -88633,9 +88924,9 @@ msgstr "Es un puñado de frutos secos tostados del castaño." #: data/json/items/comestibles/nuts.json msgid "hazelnuts" msgid_plural "hazelnuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "avellanas" +msgstr[1] "avellanas" +msgstr[2] "avellanas" #. ~ Description for {'str_sp': 'hazelnuts'} #: data/json/items/comestibles/nuts.json @@ -88645,9 +88936,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted edamame" msgid_plural "roasted edamame" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "edamame tostado" +msgstr[1] "edamame tostado" +msgstr[2] "edamame tostado" #. ~ Description for {'str_sp': 'roasted edamame'} #: data/json/items/comestibles/nuts.json @@ -88657,9 +88948,9 @@ msgstr "Es edamame tostado, algo para picar saludable para el corazón." #: data/json/items/comestibles/nuts.json msgid "roasted soy nuts" msgid_plural "roasted soy nuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "porotos de soja tostados" +msgstr[1] "porotos de soja tostados" +msgstr[2] "porotos de soja tostados" #. ~ Description for {'str_sp': 'roasted soy nuts'} #: data/json/items/comestibles/nuts.json @@ -88669,9 +88960,9 @@ msgstr "Son porotos de soja tostados." #: data/json/items/comestibles/nuts.json msgid "roasted hazelnuts" msgid_plural "roasted hazelnuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "avellanas tostadas" +msgstr[1] "avellanas tostadas" +msgstr[2] "avellanas tostadas" #. ~ Description for {'str_sp': 'roasted hazelnuts'} #: data/json/items/comestibles/nuts.json @@ -88693,9 +88984,9 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted hickory nuts" msgid_plural "roasted hickory nuts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nueces hickory tostadas" +msgstr[1] "nueces hickory tostadas" +msgstr[2] "nueces hickory tostadas" #. ~ Description for {'str_sp': 'roasted hickory nuts'} #: data/json/items/comestibles/nuts.json @@ -88705,9 +88996,9 @@ msgstr "Es un puñado de nueces tostadas de un nogal americano o hickory." #: data/json/items/comestibles/nuts.json msgid "hickory nut ambrosia" msgid_plural "hickory nut ambrosias" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ambrosía de nuez hickory" +msgstr[1] "ambrosías de nuez hickory" +msgstr[2] "ambrosías de nuez hickory" #. ~ Description for hickory nut ambrosia #: data/json/items/comestibles/nuts.json @@ -88776,9 +89067,9 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "liver & onions" msgid_plural "liver & onions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hígado con cebollas" +msgstr[1] "hígado con cebollas" +msgstr[2] "hígado con cebollas" #. ~ Description for {'str_sp': 'liver & onions'} #: data/json/items/comestibles/offal_dishes.json @@ -88788,9 +89079,9 @@ msgstr "Es la clásica manera de hacer hígado." #: data/json/items/comestibles/offal_dishes.json msgid "fried liver" msgid_plural "fried livers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hígado frito" +msgstr[1] "hígados fritos" +msgstr[2] "hígados fritos" #. ~ Description for fried liver #. ~ Description for deep-fried tripe @@ -88801,9 +89092,9 @@ msgstr "¡No hay nada más sabroso que algo bien frito!" #: data/json/items/comestibles/offal_dishes.json msgid "humble pie" msgid_plural "humble pies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tarta humillada" +msgstr[1] "tartas humilladas" +msgstr[2] "tartas humilladas" #. ~ Description for humble pie #: data/json/items/comestibles/offal_dishes.json @@ -88817,9 +89108,9 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "stewed tripe" msgid_plural "stewed tripes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guiso de tripa" +msgstr[1] "guisos de tripa" +msgstr[2] "guisos de tripa" #. ~ Description for stewed tripe #: data/json/items/comestibles/offal_dishes.json @@ -88833,16 +89124,16 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "deep-fried tripe" msgid_plural "deep-fried tripes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tripa frita" +msgstr[1] "tripas fritas" +msgstr[2] "tripas fritas" #: data/json/items/comestibles/offal_dishes.json msgid "leverpostej" msgid_plural "leverpostej" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leverpostej" +msgstr[1] "leverpostej" +msgstr[2] "leverpostej" #. ~ Description for {'str_sp': 'leverpostej'} #: data/json/items/comestibles/offal_dishes.json @@ -88855,9 +89146,9 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "cooked brains" msgid_plural "cooked brains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cerebro cocinado" +msgstr[1] "cerebros cocinados" +msgstr[2] "cerebros cocinados" #. ~ Description for {'str_sp': 'cooked brains'} #: data/json/items/comestibles/offal_dishes.json @@ -88872,9 +89163,9 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "fried brain" msgid_plural "fried brains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cerebro frito" +msgstr[1] "cerebros fritos" +msgstr[2] "cerebros fritos" #. ~ Description for fried brain #: data/json/items/comestibles/offal_dishes.json @@ -88884,9 +89175,9 @@ msgstr "No sé qué esperabas. Está frito." #: data/json/items/comestibles/offal_dishes.json msgid "cooked kidney" msgid_plural "cooked kidneys" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "riñón cocinado" +msgstr[1] "riñones cocinados" +msgstr[2] "riñones cocinados" #. ~ Description for cooked kidney #: data/json/items/comestibles/offal_dishes.json @@ -88896,9 +89187,9 @@ msgstr "No, esto no son alubias." #: data/json/items/comestibles/offal_dishes.json msgid "deviled kidney" msgid_plural "deviled kidneys" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "riñón relleno" +msgstr[1] "riñones rellenos" +msgstr[2] "riñones rellenos" #. ~ Description for deviled kidney #: data/json/items/comestibles/offal_dishes.json @@ -88908,9 +89199,9 @@ msgstr "Es una deliciosa manera de preparar riñón." #: data/json/items/comestibles/offal_dishes.json msgid "cooked sweetbread" msgid_plural "cooked sweetbreads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "molleja cocinada" +msgstr[1] "mollejas cocinadas" +msgstr[2] "mollejas cocinadas" #. ~ Description for cooked sweetbread #: data/json/items/comestibles/offal_dishes.json @@ -88920,9 +89211,9 @@ msgstr "Comúnmente, es una exquisitez, pero le falta un poco de... algo." #: data/json/items/comestibles/offal_dishes.json msgid "grilled sweetbread" msgid_plural "grilled sweetbreads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "molleja asada" +msgstr[1] "mollejas asadas" +msgstr[2] "mollejas asadas" #. ~ Description for grilled sweetbread #: data/json/items/comestibles/offal_dishes.json @@ -88932,9 +89223,9 @@ msgstr "¡Muy deliciosa!" #: data/json/items/comestibles/offal_dishes.json msgid "cooked liver" msgid_plural "cooked livers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hígado cocinado" +msgstr[1] "hígados cocinados" +msgstr[2] "hígados cocinados" #. ~ Description for cooked liver #: data/json/items/comestibles/offal_dishes.json @@ -88950,9 +89241,9 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "canned liver" msgid_plural "canned livers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hígado enlatado" +msgstr[1] "hígados enlatados" +msgstr[2] "hígados enlatados" #. ~ Description for canned liver #: data/json/items/comestibles/offal_dishes.json @@ -88981,9 +89272,9 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "lung provence" msgid_plural "lung provences" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hígado a la provenzal" +msgstr[1] "hígados a la provenzal" +msgstr[2] "hígados a la provenzal" #. ~ Description for lung provence #: data/json/items/comestibles/offal_dishes.json @@ -89007,9 +89298,9 @@ msgstr "Es una comida alemana que se hace con pulmón." #: data/json/items/comestibles/offal_dishes.json msgid "scrambled eggs and brain" msgid_plural "scrambled eggs and brains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevos revueltos con cerebro" +msgstr[1] "huevos revueltos con cerebro" +msgstr[2] "huevos revueltos con cerebro" #. ~ Description for scrambled eggs and brain #: data/json/items/comestibles/offal_dishes.json @@ -89036,9 +89327,9 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "homemade hot dog" msgid_plural "homemade hot dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pancho casero" +msgstr[1] "panchos caseros" +msgstr[2] "panchos caseros" #: data/json/items/comestibles/offal_dishes.json msgid "fried offal" @@ -89076,9 +89367,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "diet pill" msgid_plural "diet pills" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pastilla dietética" +msgstr[1] "pastillas dietéticas" +msgstr[2] "pastillas dietéticas" #. ~ Description for diet pill #: data/json/items/comestibles/other.json @@ -89213,9 +89504,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "yeast" msgid_plural "yeast" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "levadura" +msgstr[1] "levadura" +msgstr[2] "levadura" #. ~ Description for {'str_sp': 'yeast'} #: data/json/items/comestibles/other.json @@ -89228,9 +89519,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "bone meal" msgid_plural "bone meal" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "harina de hueso" +msgstr[1] "harina de hueso" +msgstr[2] "harina de hueso" #. ~ Description for {'str_sp': 'bone meal'} #: data/json/items/comestibles/other.json @@ -89242,9 +89533,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "tainted bone meal" msgid_plural "tainted bone meal" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "harina de hueso contaminado" +msgstr[1] "harina de hueso contaminado" +msgstr[2] "harina de hueso contaminado" #. ~ Description for {'str_sp': 'tainted bone meal'} #: data/json/items/comestibles/other.json @@ -89269,9 +89560,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "cardboard" msgid_plural "cardboards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartón" +msgstr[1] "cartones" +msgstr[2] "cartones" #. ~ Description for cardboard #: data/json/items/comestibles/other.json @@ -89343,16 +89634,16 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "fried tofu" msgid_plural "fried tofu" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tofu frito" +msgstr[1] "tofu frito" +msgstr[2] "tofu frito" #: data/json/items/comestibles/other.json msgid "dehydrated tofu" msgid_plural "dehydrated tofu" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tofu deshidratado" +msgstr[1] "tofu deshidratado" +msgstr[2] "tofu deshidratado" #. ~ Description for {'str_sp': 'dehydrated tofu'} #: data/json/items/comestibles/other.json @@ -89362,9 +89653,9 @@ msgstr "Es tofu deshidratado, sellado y muy firme para que dure mucho tiempo." #: data/json/items/comestibles/other.json msgid "soybeans" msgid_plural "soybeans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "porotos de soja" +msgstr[1] "porotos de soja" +msgstr[2] "porotos de soja" #. ~ Description for {'str_sp': 'soybeans'} #: data/json/items/comestibles/other.json @@ -89378,9 +89669,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "raw edamame" msgid_plural "raw edamames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "edamame crudo" +msgstr[1] "edamames crudos" +msgstr[2] "edamames crudos" #. ~ Description for raw edamame #: data/json/items/comestibles/other.json @@ -89394,9 +89685,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "dried lentils" msgid_plural "dried lentils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lentejas deshidratadas" +msgstr[1] "lentejas deshidratadas" +msgstr[2] "lentejas deshidratadas" #. ~ Description for {'str_sp': 'dried lentils'} #: data/json/items/comestibles/other.json @@ -89409,9 +89700,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "Foodplace's delicious food™" msgid_plural "Foodplace's delicious food™" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "deliciosa comida™ de Foodplace" +msgstr[1] "deliciosa comida™ de Foodplace" +msgstr[2] "deliciosa comida™ de Foodplace" #. ~ Description for {'str_sp': "Foodplace's delicious food™"} #: data/json/items/comestibles/other.json @@ -89425,9 +89716,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "cooked lentils" msgid_plural "cooked lentils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lentejas cocinadas" +msgstr[1] "lentejas cocinadas" +msgstr[2] "lentejas cocinadas" #. ~ Description for {'str_sp': 'cooked lentils'} #: data/json/items/comestibles/other.json @@ -89453,9 +89744,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "Kentucky coffee grounds" msgid_plural "Kentucky coffee grounds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "café Kentucky molido" +msgstr[1] "café Kentucky molido" +msgstr[2] "café Kentucky molido" #. ~ Description for {'str_sp': 'Kentucky coffee grounds'} #: data/json/items/comestibles/other.json @@ -89501,9 +89792,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "embalmed human brain" msgid_plural "embalmed human brains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cerebro humano embalsamado" +msgstr[1] "cerebros humanos embalsamados" +msgstr[2] "cerebros humanos embalsamados" #. ~ Description for {'str': 'embalmed human brain'} #: data/json/items/comestibles/other.json @@ -89593,9 +89884,9 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "nectar" msgid_plural "nectars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "néctar" +msgstr[1] "néctares" +msgstr[2] "néctares" #. ~ Description for {'str': 'nectar'} #: data/json/items/comestibles/other.json @@ -89613,9 +89904,9 @@ msgstr[2] "bebidas de proteína" #: data/json/items/comestibles/protein.json msgid "soylent green drink" msgid_plural "soylent green drinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bebida de soylent verde" +msgstr[1] "bebidas de soylent verde" +msgstr[2] "bebidas de soylent verde" #. ~ Conditional name for protein drink when COMPONENT_ID matches mutant #. ~ Conditional name for {'str_sp': 'protein powder'} when COMPONENT_ID @@ -89627,9 +89918,9 @@ msgstr[2] "" #, c-format msgid "perturbing %s" msgid_plural "perturbing %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perturbador %s" +msgstr[1] "perturbadores %s" +msgstr[2] "perturbadores %s" #. ~ Description for protein drink #: data/json/items/comestibles/protein.json @@ -89643,18 +89934,18 @@ msgstr "" #: data/json/items/comestibles/protein.json msgid "protein powder" msgid_plural "protein powder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "polvo de proteína" +msgstr[1] "polvo de proteína" +msgstr[2] "polvo de proteína" #. ~ Conditional name for {'str_sp': 'protein powder'} when FLAG matches #. CANNIBALISM #: data/json/items/comestibles/protein.json msgid "soylent green powder" msgid_plural "soylent green powder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "polvo de soylent verde" +msgstr[1] "polvo de soylent verde" +msgstr[2] "polvo de soylent verde" #. ~ Description for {'str_sp': 'protein powder'} #: data/json/items/comestibles/protein.json @@ -89668,9 +89959,9 @@ msgstr "" #: data/json/items/comestibles/protein.json msgid "protein ration" msgid_plural "protein rations" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ración de proteína" +msgstr[1] "raciones de proteína" +msgstr[2] "raciones de proteína" #. ~ Description for {'str': 'protein ration'} #: data/json/items/comestibles/protein.json @@ -89696,17 +89987,17 @@ msgstr "" #: data/json/items/comestibles/protein.json msgid "protein shake" msgid_plural "protein shakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "licuado de proteína" +msgstr[1] "licuados de proteína" +msgstr[2] "licuados de proteína" #. ~ Conditional name for protein shake when FLAG matches CANNIBALISM #: data/json/items/comestibles/protein.json msgid "soylent green shake" msgid_plural "soylent green shakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "licuado de soylent verde" +msgstr[1] "licuados de soylent verde" +msgstr[2] "licuados de soylent verde" #. ~ Description for protein shake #: data/json/items/comestibles/protein.json @@ -89720,18 +90011,18 @@ msgstr "" #: data/json/items/comestibles/protein.json msgid "fortified protein shake" msgid_plural "fortified protein shakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "licuado de proteína fortificado" +msgstr[1] "licuados de proteína fortificados" +msgstr[2] "licuados de proteína fortificados" #. ~ Conditional name for fortified protein shake when FLAG matches #. CANNIBALISM #: data/json/items/comestibles/protein.json msgid "fortified soylent green shake" msgid_plural "fortified soylent green shakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "licuado de soylent verde fortificado" +msgstr[1] "licuados de soylent verde fortificados" +msgstr[2] "licuados de soylent verde fortificados" #. ~ Description for fortified protein shake #: data/json/items/comestibles/protein.json @@ -89800,9 +90091,9 @@ msgstr "Cítrico muy agrio. Se puede comer si quieres." #: data/json/items/comestibles/raw_fruit.json msgid "blueberries" msgid_plural "blueberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "moras" +msgstr[1] "moras" +msgstr[2] "moras" #. ~ Description for {'str_sp': 'blueberries'} #: data/json/items/comestibles/raw_fruit.json @@ -89812,9 +90103,9 @@ msgstr "Son azules, pero eso no significa que sean de la realeza." #: data/json/items/comestibles/raw_fruit.json msgid "strawberries" msgid_plural "strawberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "frutillas" +msgstr[1] "frutillas" +msgstr[2] "frutillas" #. ~ Description for {'str_sp': 'strawberries'} #: data/json/items/comestibles/raw_fruit.json @@ -89824,9 +90115,9 @@ msgstr "Es una baya sabrosa y jugosa. A menudo crece silvestre en los campos." #: data/json/items/comestibles/raw_fruit.json msgid "cranberries" msgid_plural "cranberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arándanos" +msgstr[1] "arándanos" +msgstr[2] "arándanos" #. ~ Description for {'str_sp': 'cranberries'} #: data/json/items/comestibles/raw_fruit.json @@ -89836,9 +90127,9 @@ msgstr "Arándanos rojos y agrios. Buenos para la salud." #: data/json/items/comestibles/raw_fruit.json msgid "raspberries" msgid_plural "raspberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "frambuesas" +msgstr[1] "frambuesas" +msgstr[2] "frambuesas" #. ~ Description for {'str_sp': 'raspberries'} #: data/json/items/comestibles/raw_fruit.json @@ -89848,9 +90139,9 @@ msgstr "Una frambuesa roja y dulce." #: data/json/items/comestibles/raw_fruit.json msgid "huckleberries" msgid_plural "huckleberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arándanos agrios" +msgstr[1] "arándanos agrios" +msgstr[2] "arándanos agrios" #. ~ Description for {'str_sp': 'huckleberries'} #: data/json/items/comestibles/raw_fruit.json @@ -89860,9 +90151,9 @@ msgstr "Son arándanos agrios, a menudo confundidos con las moras azules." #: data/json/items/comestibles/raw_fruit.json msgid "mulberries" msgid_plural "mulberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "moras" +msgstr[1] "moras" +msgstr[2] "moras" #. ~ Description for {'str_sp': 'mulberries'} #: data/json/items/comestibles/raw_fruit.json @@ -89876,9 +90167,9 @@ msgstr "" #: data/json/items/comestibles/raw_fruit.json msgid "elderberries" msgid_plural "elderberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bayas del saúco" +msgstr[1] "bayas del saúco" +msgstr[2] "bayas del saúco" #. ~ Description for {'str_sp': 'elderberries'} #: data/json/items/comestibles/raw_fruit.json @@ -89890,9 +90181,9 @@ msgstr "" #: data/json/items/comestibles/raw_fruit.json msgid "rose hips" msgid_plural "rose hips" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "escaramujos" +msgstr[1] "escaramujos" +msgstr[2] "escaramujos" #. ~ Description for {'str_sp': 'rose hips'} #: data/json/items/comestibles/raw_fruit.json @@ -89942,9 +90233,9 @@ msgstr "Una fruta cítrica, cuyo gusto va desde lo agrio hasta lo semidulce." #: data/json/items/comestibles/raw_fruit.json msgid "cherries" msgid_plural "cherries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cerezas" +msgstr[1] "cerezas" +msgstr[2] "cerezas" #. ~ Description for {'str_sp': 'cherries'} #: data/json/items/comestibles/raw_fruit.json @@ -89969,9 +90260,9 @@ msgstr "" #: data/json/items/comestibles/raw_fruit.json msgid "grapes" msgid_plural "grapes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "uvas" +msgstr[1] "uvas" +msgstr[2] "uvas" #. ~ Description for {'str_sp': 'grapes'} #: data/json/items/comestibles/raw_fruit.json @@ -90044,9 +90335,9 @@ msgstr "Una fruta grande y muy dulce." #: data/json/items/comestibles/raw_fruit.json msgid "blackberries" msgid_plural "blackberries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zarzamoras" +msgstr[1] "zarzamoras" +msgstr[2] "zarzamoras" #. ~ Description for {'str_sp': 'blackberries'} #: data/json/items/comestibles/raw_fruit.json @@ -90109,9 +90400,9 @@ msgstr "" #: data/json/items/comestibles/raw_fruit.json msgid "apricots" msgid_plural "apricots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "damascos" +msgstr[1] "damascos" +msgstr[2] "damascos" #. ~ Description for {'str_sp': 'apricots'} #: data/json/items/comestibles/raw_fruit.json @@ -90121,9 +90412,9 @@ msgstr "Una fruta de cáscara suave, parecida al melocotón." #: data/json/items/comestibles/raw_fruit.json msgid "cholla bud" msgid_plural "cholla buds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capullo de choya" +msgstr[1] "capullos de choya" +msgstr[2] "capullos de choya" #. ~ Description for cholla bud #: data/json/items/comestibles/raw_fruit.json @@ -90137,9 +90428,9 @@ msgstr "" #: data/json/items/comestibles/raw_fruit.json msgid "cactus pad" msgid_plural "cactus pads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nopal" +msgstr[1] "nopales" +msgstr[2] "nopales" #. ~ Description for cactus pad #: data/json/items/comestibles/raw_fruit.json @@ -90167,9 +90458,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "bee balm" msgid_plural "bee balms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "monarda" +msgstr[1] "monardas" +msgstr[2] "monardas" #. ~ Description for {'str': 'bee balm'} #: data/json/items/comestibles/raw_veggy.json @@ -90213,9 +90504,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "cabbage" msgid_plural "cabbages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "repollo" +msgstr[1] "repollos" +msgstr[2] "repollos" #. ~ Description for cabbage #: data/json/items/comestibles/raw_veggy.json @@ -90264,9 +90555,9 @@ msgstr "Una raíz vegetal saludable. ¡Rica en vitamina A!" #: data/json/items/comestibles/raw_veggy.json msgid "cattail rhizome" msgid_plural "cattail rhizomes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rizoma de junco" +msgstr[1] "rizomas de junco" +msgstr[2] "rizomas de junco" #. ~ Description for {'str': 'cattail rhizome'} #: data/json/items/comestibles/raw_veggy.json @@ -90282,9 +90573,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "cattail stalk" msgid_plural "cattail stalks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tallo de junco" +msgstr[1] "tallos de junco" +msgstr[2] "tallos de junco" #. ~ Description for {'str': 'cattail stalk'} #: data/json/items/comestibles/raw_veggy.json @@ -90343,9 +90634,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "chili pepper" msgid_plural "chili peppers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ají" +msgstr[1] "ajíes" +msgstr[2] "ajíes" #. ~ Description for chili pepper #: data/json/items/comestibles/raw_veggy.json @@ -90385,9 +90676,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "salsify" msgid_plural "salsify" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salsifí" +msgstr[1] "salsifí" +msgstr[2] "salsifí" #. ~ Description for {'str_sp': 'salsify'} #: data/json/items/comestibles/raw_veggy.json @@ -90411,9 +90702,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "wild root" msgid_plural "wild roots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "raíz silvestre" +msgstr[1] "raíces silvestres" +msgstr[2] "raíces silvestres" #. ~ Description for {'str': 'wild root'} #: data/json/items/comestibles/raw_veggy.json @@ -90428,9 +90719,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "dogbane" msgid_plural "dogbanes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "apocino" +msgstr[1] "apocinos" +msgstr[2] "apocinos" #. ~ Description for dogbane #: data/json/items/comestibles/raw_veggy.json @@ -90441,9 +90732,9 @@ msgstr "Un tallo de apocino. Es muy fibroso y levemente venenoso." #: data/json/items/comestibles/raw_veggy.json msgid "garlic bulb" msgid_plural "garlic bulbs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cabeza de ajo" +msgstr[1] "cabezas de ajo" +msgstr[2] "cabezas de ajo" #. ~ Description for garlic bulb #: data/json/items/comestibles/raw_veggy.json @@ -90471,9 +90762,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "horseradish root" msgid_plural "horseradish roots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "raíz de rábano" +msgstr[1] "raíces de rábano" +msgstr[2] "raíces de rábano" #. ~ Description for {'str': 'horseradish root'} #: data/json/items/comestibles/raw_veggy.json @@ -90501,9 +90792,9 @@ msgstr "Una planta fresca de lechuga arrepollada." #: data/json/items/comestibles/seed.json msgid "mugwort" msgid_plural "mugworts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "abrótano" +msgstr[1] "abrótanos" +msgstr[2] "abrótanos" #. ~ Description for mugwort #: data/json/items/comestibles/raw_veggy.json @@ -90530,9 +90821,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "fungal fluid sac" msgid_plural "fungal fluid sacs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de fluido fúngico" +msgstr[1] "bolsas de fluido fúngico" +msgstr[2] "bolsas de fluido fúngico" #. ~ Description for fungal fluid sac #: data/json/items/comestibles/raw_veggy.json @@ -90546,9 +90837,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "raw popcorn" msgid_plural "raw popcorn" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maíz pisingallo" +msgstr[1] "maíces pisingallo" +msgstr[2] "maíces pisingallo" #. ~ Description for {'str_sp': 'raw popcorn'} #: data/json/items/comestibles/raw_veggy.json @@ -90577,9 +90868,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "pumpkin" msgid_plural "pumpkins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "calabaza" +msgstr[1] "calabazas" +msgstr[2] "calabazas" #. ~ Description for pumpkin #: data/json/items/comestibles/raw_veggy.json @@ -90593,9 +90884,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "horseradish greens" msgid_plural "horseradish greens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hojas de rábano" +msgstr[1] "hojas de rábano" +msgstr[2] "hojas de rábano" #. ~ Description for {'str_sp': 'horseradish greens'} #: data/json/items/comestibles/raw_veggy.json @@ -90609,9 +90900,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "dandelions" msgid_plural "dandelions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "diente de león" +msgstr[1] "diente de león" +msgstr[2] "diente de león" #. ~ Description for {'str_sp': 'dandelions'} #: data/json/items/comestibles/raw_veggy.json @@ -90625,9 +90916,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "burdocks" msgid_plural "burdocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bardana" +msgstr[1] "bardana" +msgstr[2] "bardana" #. ~ Description for {'str_sp': 'burdocks'} #: data/json/items/comestibles/raw_veggy.json @@ -90718,9 +91009,9 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "alien fungus chunk" msgid_plural "alien fungus chunks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de hongo alienígena" +msgstr[1] "pedazos de hongos alienígena" +msgstr[2] "pedazos de hongos alienígena" #. ~ Description for {'str': 'alien fungus chunk'} #: data/json/items/comestibles/raw_veggy.json @@ -90764,9 +91055,9 @@ msgstr "Un sabroso zapallito de verano." #: data/json/items/comestibles/seed.json msgid "canola" msgid_plural "canolas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "canola" +msgstr[1] "canolas" +msgstr[2] "canolas" #. ~ Description for canola #: data/json/items/comestibles/raw_veggy.json @@ -90795,9 +91086,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "raw lentils" msgid_plural "raw lentils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lentejas crudas" +msgstr[1] "lentejas crudas" +msgstr[2] "lentejas crudas" #. ~ Description for {'str_sp': 'raw lentils'} #: data/json/items/comestibles/raw_veggy.json @@ -90807,9 +91098,9 @@ msgstr "Son lentejas crudas, sin cocinar. Deberían ser cocinadas." #: data/json/items/comestibles/raw_veggy.json msgid "fiddleheads" msgid_plural "fiddleheads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brotes de helecho" +msgstr[1] "brotes de helecho" +msgstr[2] "brotes de helecho" #. ~ Description for {'str_sp': 'fiddleheads'} #: data/json/items/comestibles/raw_veggy.json @@ -90850,9 +91141,9 @@ msgstr[2] "sandwiches de lujo" #: data/json/items/comestibles/sandwich.json msgid "\"deluxe\" sandwich" msgid_plural "\"deluxe\" sandwiches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sánguche \"de lujo\"" +msgstr[1] "sánguches \"de lujo\"" +msgstr[2] "sánguches \"de lujo\"" #. ~ Description for {'str': 'deluxe sandwich', 'str_pl': 'deluxe sandwiches'} #: data/json/items/comestibles/sandwich.json @@ -90905,9 +91196,9 @@ msgstr "Es un delicioso sandwich de mermelada." #: data/json/items/comestibles/sandwich.json msgid "fairy bread" msgid_plural "fairy bread" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pan de hadas" +msgstr[1] "panes de hadas" +msgstr[2] "panes de hadas" #. ~ Description for {'str_sp': 'fairy bread'} #: data/json/items/comestibles/sandwich.json @@ -90984,9 +91275,9 @@ msgstr[2] "sandwiches de vago" #, c-format msgid "mutant %s" msgid_plural "mutant %s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutante %s" +msgstr[1] "mutantes %s" +msgstr[2] "mutantes %s" #. ~ Description for {'str': 'meat sandwich', 'str_pl': 'meat sandwiches'} #: data/json/items/comestibles/sandwich.json @@ -91074,9 +91365,9 @@ msgstr "Es un delicioso sandwich de pescado." #: data/json/items/comestibles/sandwich.json msgid "fish and spinach bagel" msgid_plural "fish and spinach bagels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rosca de espinaca y pescado" +msgstr[1] "roscas de espinaca y pescado" +msgstr[2] "roscas de espinaca y pescado" #. ~ Description for {'str': 'fish and spinach bagel'} #: data/json/items/comestibles/sandwich.json @@ -91086,9 +91377,9 @@ msgstr "Es una deliciosa rosca de pescado con espinaca y huevos." #: data/json/items/comestibles/sandwich.json msgid "BLT" msgid_plural "BLTs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sánguche BLT" +msgstr[1] "sánguches BLT" +msgstr[2] "sánguches BLT" #. ~ Description for {'str': 'BLT'} #: data/json/items/comestibles/sandwich.json @@ -91107,9 +91398,9 @@ msgstr[2] "semillas" #: data/json/items/comestibles/seed.json msgid "fruit seeds" msgid_plural "fruit seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de fruta" +msgstr[1] "semillas de fruta" +msgstr[2] "semillas de fruta" #: data/json/items/comestibles/seed.json msgid "mushroom spores" @@ -91190,9 +91481,9 @@ msgstr "arándano" #: data/json/items/comestibles/seed.json msgid "huckleberry seeds" msgid_plural "huckleberry seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de arándano agrio" +msgstr[1] "semillas de arándano agrio" +msgstr[2] "semillas de arándano agrio" #. ~ Description for {'str_sp': 'huckleberry seeds'} #: data/json/items/comestibles/seed.json @@ -91206,9 +91497,9 @@ msgstr "arándano agrio" #: data/json/items/comestibles/seed.json msgid "mulberry seeds" msgid_plural "mulberry seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de mora" +msgstr[1] "semillas de mora" +msgstr[2] "semillas de mora" #. ~ Description for {'str_sp': 'mulberry seeds'} #: data/json/items/comestibles/seed.json @@ -91222,9 +91513,9 @@ msgstr "mora" #: data/json/items/comestibles/seed.json msgid "elderberry seeds" msgid_plural "elderberry seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de bayas del saúco" +msgstr[1] "semillas de bayas del saúco" +msgstr[2] "semillas de bayas del saúco" #. ~ Description for {'str_sp': 'elderberry seeds'} #: data/json/items/comestibles/seed.json @@ -91321,9 +91612,9 @@ msgstr "tabaco" #: data/json/items/comestibles/seed.json msgid "barley seeds" msgid_plural "barley seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de cebada" +msgstr[1] "semillas de cebada" +msgstr[2] "semillas de cebada" #. ~ Description for {'str_sp': 'barley seeds'} #: data/json/items/comestibles/seed.json @@ -91333,9 +91624,9 @@ msgstr "Algunas semillas de cebada." #: data/json/items/comestibles/seed.json msgid "sugar beet seeds" msgid_plural "sugar beet seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de remolacha azucarera" +msgstr[1] "semillas de remolacha azucarera" +msgstr[2] "semillas de remolacha azucarera" #. ~ Description for {'str_sp': 'sugar beet seeds'} #: data/json/items/comestibles/seed.json @@ -91451,9 +91742,9 @@ msgstr "ajo" #: data/json/items/comestibles/seed.json msgid "cattail seeds" msgid_plural "cattail seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de junco" +msgstr[1] "semillas de junco" +msgstr[2] "semillas de junco" #. ~ Description for {'str_sp': 'cattail seeds'} #: data/json/items/comestibles/seed.json @@ -91467,9 +91758,9 @@ msgstr "junco" #: data/json/items/comestibles/seed.json msgid "dahlia seeds" msgid_plural "dahlia seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de dalia" +msgstr[1] "semillas de dalia" +msgstr[2] "semillas de dalia" #. ~ Description for {'str_sp': 'dahlia seeds'} #: data/json/items/comestibles/seed.json @@ -91479,9 +91770,9 @@ msgstr "Son unas semillas de dalia." #: data/json/items/comestibles/seed.json msgid "salsify seeds" msgid_plural "salsify seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de salsifí" +msgstr[1] "semillas de salsifí" +msgstr[2] "semillas de salsifí" #. ~ Description for {'str_sp': 'salsify seeds'} #: data/json/items/comestibles/seed.json @@ -91491,9 +91782,9 @@ msgstr "Son unas semillas de salsifí." #: data/json/items/comestibles/seed.json msgid "chicory seeds" msgid_plural "chicory seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de achicoria" +msgstr[1] "semillas de achicoria" +msgstr[2] "semillas de achicoria" #. ~ Description for {'str_sp': 'chicory seeds'} #: data/json/items/comestibles/seed.json @@ -91503,9 +91794,9 @@ msgstr "Son unas semillas de achicoria." #: data/json/items/comestibles/seed.json msgid "wild root seeds" msgid_plural "wild root seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de raíces silvestres" +msgstr[1] "semillas de raíces silvestres" +msgstr[2] "semillas de raíces silvestres" #. ~ Description for {'str_sp': 'wild root seeds'} #: data/json/items/comestibles/seed.json @@ -91515,9 +91806,9 @@ msgstr "Son unas semillas de una flor blanca." #: data/json/items/comestibles/seed.json msgid "decorative plant seeds" msgid_plural "decorative plant seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de planta decorativa" +msgstr[1] "semillas de planta decorativa" +msgstr[2] "semillas de planta decorativa" #. ~ Description for {'str_sp': 'decorative plant seeds'} #: data/json/items/comestibles/seed.json @@ -91535,9 +91826,9 @@ msgstr "planta decorativa" #: data/json/items/comestibles/seed.json msgid "cactus seeds" msgid_plural "cactus seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de cactus" +msgstr[1] "semillas de cactus" +msgstr[2] "semillas de cactus" #. ~ Description for {'str_sp': 'cactus seeds'} #: data/json/items/comestibles/seed.json @@ -91552,9 +91843,9 @@ msgstr "cactus" #: data/json/items/comestibles/seed.json msgid "garlic clove" msgid_plural "garlic cloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "diente de ajo" +msgstr[1] "dientes de ajo" +msgstr[2] "dientes de ajo" #. ~ Description for {'str': 'garlic clove'} #: data/json/items/comestibles/seed.json @@ -91661,9 +91952,9 @@ msgstr "Algunas semillas de hongos." #: data/json/items/comestibles/seed.json data/mods/No_Fungi/comestibles.json msgid "Marloss seed" msgid_plural "Marloss seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semilla de Marloss" +msgstr[1] "semillas de Marloss" +msgstr[2] "semillas de Marloss" #. ~ Description for {'str': 'Marloss seed'} #: data/json/items/comestibles/seed.json @@ -91679,9 +91970,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "bean seeds" msgid_plural "bean seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "porotos semillas" +msgstr[1] "porotos semillas" +msgstr[2] "porotos semillas" #. ~ Description for {'str_sp': 'bean seeds'} #: data/json/items/comestibles/seed.json @@ -91695,9 +91986,9 @@ msgstr "alubias" #: data/json/items/comestibles/seed.json msgid "soybean seeds" msgid_plural "soybean seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "porotos semilla de soja" +msgstr[1] "porotos semilla de soja" +msgstr[2] "porotos semilla de soja" #. ~ Description for {'str_sp': 'soybean seeds'} #: data/json/items/comestibles/seed.json @@ -91733,9 +92024,9 @@ msgstr "Son unas semillas de tomillo." #: data/json/items/comestibles/spice.json msgid "thyme" msgid_plural "thymes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tomillo" +msgstr[1] "tomillos" +msgstr[2] "tomillos" #: data/json/items/comestibles/seed.json msgid "canola seeds" @@ -91870,9 +92161,9 @@ msgstr "Son unas semillas de diente de león." #: data/json/items/comestibles/seed.json msgid "burdock seeds" msgid_plural "burdock seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de bardana" +msgstr[1] "semillas de bardana" +msgstr[2] "semillas de bardana" #. ~ Description for {'str_sp': 'burdock seeds'} #: data/json/items/comestibles/seed.json @@ -91993,9 +92284,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "Kentucky coffee pod" msgid_plural "Kentucky coffee pods" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "vaina de café Kentucky" +msgstr[1] "vainas de café Kentucky" +msgstr[2] "vainas de café Kentucky" #. ~ Description for {'str': 'Kentucky coffee pod'} #: data/json/items/comestibles/seed.json @@ -92035,9 +92326,9 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "chamomile seeds" msgid_plural "chamomile seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de manzanilla" +msgstr[1] "semillas de manzanilla" +msgstr[2] "semillas de manzanilla" #. ~ Description for {'str_sp': 'chamomile seeds'} #: data/json/items/comestibles/seed.json @@ -92047,9 +92338,9 @@ msgstr "Son unas semillas de manzanilla." #: data/json/items/comestibles/seed.json msgid "popcorn seeds" msgid_plural "popcorn seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de maíz pisingallo" +msgstr[1] "semillas de maíz pisingallo" +msgstr[2] "semillas de maíz pisingallo" #. ~ Description for {'str_sp': 'popcorn seeds'} #: data/json/items/comestibles/seed.json @@ -92059,9 +92350,9 @@ msgstr "Son unas semillas de maíz pisingallo." #: data/json/items/comestibles/seed.json msgid "horseradish seeds" msgid_plural "horseradish seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de rábano" +msgstr[1] "semillas de rábano" +msgstr[2] "semillas de rábano" #. ~ Description for {'str_sp': 'horseradish seeds'} #: data/json/items/comestibles/seed.json @@ -92071,9 +92362,9 @@ msgstr "Son unas semillas de rábano." #: data/json/items/comestibles/seed.json msgid "mustard seeds" msgid_plural "mustard seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "semillas de mostaza" +msgstr[1] "semillas de mostaza" +msgstr[2] "semillas de mostaza" #. ~ Description for {'str_sp': 'mustard seeds'} #: data/json/items/comestibles/seed.json @@ -92174,9 +92465,9 @@ msgstr[2] "currys con carne" #: data/json/items/comestibles/soup.json msgid "creature curry" msgid_plural "creature curries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "curry de criatura" +msgstr[1] "currys de criatura" +msgstr[2] "currys de criatura" #. ~ Description for {'str': 'curry with meat', 'str_pl': 'curries with meat'} #: data/json/items/comestibles/soup.json @@ -92195,9 +92486,9 @@ msgstr[2] "sopas de los bosques" #: data/json/items/comestibles/soup.json msgid "Mirkwood soup" msgid_plural "Mirkwood soups" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sopa de Bosque negro" +msgstr[1] "sopas de Bosque negro" +msgstr[2] "sopas de Bosque negro" #. ~ Description for woods soup #: data/json/items/comestibles/soup.json @@ -92263,9 +92554,9 @@ msgstr "Una sopa con pedazos de pollo y pelotas de masa. No está mal." #: data/json/items/comestibles/soup.json msgid "cullen skink" msgid_plural "cullen skinks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cullen skink" +msgstr[1] "cullen skinks" +msgstr[2] "cullen skinks" #. ~ Description for cullen skink #: data/json/items/comestibles/soup.json @@ -92390,9 +92681,9 @@ msgstr "" #: data/json/items/comestibles/spice.json msgid "sprinkles" msgid_plural "sprinkles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "confites" +msgstr[1] "confites" +msgstr[2] "confites" #. ~ Description for {'str_sp': 'sprinkles'} #: data/json/items/comestibles/spice.json @@ -92443,9 +92734,9 @@ msgstr "Es un tallo de tomillo. Tiene un olor delicioso." #: data/json/items/comestibles/spice.json msgid "mustard powder" msgid_plural "mustard powder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "polvo de mostaza" +msgstr[1] "polvo de mostaza" +msgstr[2] "polvo de mostaza" #. ~ Description for {'str_sp': 'mustard powder'} #: data/json/items/comestibles/spice.json @@ -92456,9 +92747,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "cooked cattail stalk" msgid_plural "cooked cattail stalks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tallo de junco cocinado" +msgstr[1] "tallos de junco cocinados" +msgstr[2] "tallos de junco cocinados" #. ~ Description for {'str': 'cooked cattail stalk'} #: data/json/items/comestibles/veggy_dishes.json @@ -92545,9 +92836,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "cooked burdock greens" msgid_plural "cooked burdock greens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hojas verdes de bardana cocinadas" +msgstr[1] "hojas verdes de bardana cocinadas" +msgstr[2] "hojas verdes de bardana cocinadas" #. ~ Description for {'str_sp': 'cooked burdock greens'} #: data/json/items/comestibles/veggy_dishes.json @@ -92557,9 +92848,9 @@ msgstr "Son hojas cocinadas de bardana. Sabrosas y nutritivas." #: data/json/items/comestibles/veggy_dishes.json msgid "fried burdocks" msgid_plural "fried burdocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bardana frita" +msgstr[1] "bardana frita" +msgstr[2] "bardana frita" #. ~ Description for {'str_sp': 'fried burdocks'} #: data/json/items/comestibles/veggy_dishes.json @@ -92573,9 +92864,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "fried dandelions and burdocks" msgid_plural "fried dandelions burdocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dientes de león y bardana fritos" +msgstr[1] "dientes de león y bardana fritos" +msgstr[2] "dientes de león y bardana fritos" #. ~ Description for {'str': 'fried dandelions and burdocks', 'str_pl': 'fried #. dandelions burdocks'} @@ -92649,9 +92940,9 @@ msgstr "Maíz enlatado en agua. ¡A comer!" #: data/json/items/comestibles/veggy_dishes.json msgid "hominy" msgid_plural "hominy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maíz precocido" +msgstr[1] "maíz precocido" +msgstr[2] "maíz precocido" #. ~ Description for {'str_sp': 'hominy'} #: data/json/items/comestibles/veggy_dishes.json @@ -92665,9 +92956,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "cornmeal" msgid_plural "cornmeal" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "harina de maíz" +msgstr[1] "harina de maíz" +msgstr[2] "harina de maíz" #. ~ Description for {'str_sp': 'cornmeal'} #: data/json/items/comestibles/veggy_dishes.json @@ -92745,9 +93036,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "tofu fried rice" msgid_plural "tofu fried rice" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arroz frito con tofu" +msgstr[1] "arroz frito con tofu" +msgstr[2] "arroz frito con tofu" #. ~ Description for {'str_sp': 'tofu fried rice'} #: data/json/items/comestibles/veggy_dishes.json @@ -92757,9 +93048,9 @@ msgstr "Es delicioso arroz frito con tofu y verduras. Sabroso y muy rendidor." #: data/json/items/comestibles/veggy_dishes.json msgid "tofu stirfry" msgid_plural "tofu stirfry" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tofu salteado" +msgstr[1] "tofu salteado" +msgstr[2] "tofu salteado" #. ~ Description for {'str_sp': 'tofu stirfry'} #: data/json/items/comestibles/veggy_dishes.json @@ -92801,9 +93092,9 @@ msgstr "Una deliciosa patata al horno. ¿Tienes crema agria para agregarle?" #: data/json/items/comestibles/veggy_dishes.json msgid "mashed pumpkin" msgid_plural "mashed pumpkins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "puré de calabaza" +msgstr[1] "puré de calabaza" +msgstr[2] "puré de calabaza" #. ~ Description for mashed pumpkin #: data/json/items/comestibles/veggy_dishes.json @@ -92816,9 +93107,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "vegetable pie" msgid_plural "vegetable pies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tarta de verdura" +msgstr[1] "tartas de verdura" +msgstr[2] "tartas de verdura" #. ~ Description for vegetable pie #: data/json/items/comestibles/veggy_dishes.json @@ -92844,9 +93135,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "pesto" msgid_plural "pesto" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pesto" +msgstr[1] "pesto" +msgstr[2] "pesto" #. ~ Description for {'str_sp': 'pesto'} #: data/json/items/comestibles/veggy_dishes.json @@ -93005,9 +93296,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "insta-salad" msgid_plural "insta-salads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ensalada instantánea" +msgstr[1] "ensaladas instantáneas" +msgstr[2] "ensaladas instantáneas" #. ~ Description for insta-salad #: data/json/items/comestibles/veggy_dishes.json @@ -93037,9 +93328,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "roasted salsify" msgid_plural "roasted salsifies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "salsifí tostado" +msgstr[1] "salsifíes tostados" +msgstr[2] "salsifíes tostados" #. ~ Description for {'str': 'roasted salsify', 'str_pl': 'roasted salsifies'} #: data/json/items/comestibles/veggy_dishes.json @@ -93099,9 +93390,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "dehydrated alien fungus chunk" msgid_plural "dehydrated alien fungus chunks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazo de hongo alienígena deshidratado" +msgstr[1] "pedazos de hongo alienígena deshidratados" +msgstr[2] "pedazos de hongo alienígena deshidratados" #. ~ Description for dehydrated alien fungus chunk #: data/json/items/comestibles/veggy_dishes.json @@ -93132,9 +93423,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "nopalito" msgid_plural "nopalitos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nopalito" +msgstr[1] "nopalitos" +msgstr[2] "nopalitos" #. ~ Description for nopalito #: data/json/items/comestibles/veggy_dishes.json @@ -93144,9 +93435,9 @@ msgstr "Es una versión con menos espinas de los nopales de cactus." #: data/json/items/comestibles/veggy_dishes.json msgid "boiled fiddleheads" msgid_plural "boiled fiddleheads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brotes de helecho hervidos" +msgstr[1] "brotes de helecho hervidos" +msgstr[2] "brotes de helecho hervidos" #. ~ Description for {'str_sp': 'boiled fiddleheads'} #: data/json/items/comestibles/veggy_dishes.json @@ -93158,9 +93449,9 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "sauteed fiddleheads" msgid_plural "sauteed fiddleheads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brotes de helecho salteados" +msgstr[1] "brotes de helecho salteados" +msgstr[2] "brotes de helecho salteados" #. ~ Description for {'str_sp': 'sauteed fiddleheads'} #: data/json/items/comestibles/veggy_dishes.json @@ -93205,9 +93496,9 @@ msgstr "" #: data/json/items/comestibles/wheat.json msgid "raw spaghetti pasta" msgid_plural "raw spaghetti pasta" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espagueti crudo" +msgstr[1] "espagueti crudo" +msgstr[2] "espagueti crudo" #. ~ Description for {'str_sp': 'raw spaghetti pasta'} #: data/json/items/comestibles/wheat.json @@ -93221,9 +93512,9 @@ msgstr "" #: data/json/items/comestibles/wheat.json msgid "raw lasagne pasta" msgid_plural "raw lasagne pasta" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lasaña cruda" +msgstr[1] "lasaña cruda" +msgstr[2] "lasaña cruda" #. ~ Description for {'str_sp': 'raw lasagne pasta'} #: data/json/items/comestibles/wheat.json @@ -93287,9 +93578,9 @@ msgstr "Harina blanca enriquecida, útil para hornear." #: data/json/items/comestibles/wheat.json msgid "oatmeal" msgid_plural "oatmeal" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "avena" +msgstr[1] "avena" +msgstr[2] "avena" #. ~ Description for {'str_sp': 'oatmeal'} #: data/json/items/comestibles/wheat.json @@ -93308,9 +93599,9 @@ msgstr "Avena cruda." #: data/json/items/comestibles/wheat.json msgid "cooked oatmeal" msgid_plural "cooked oatmeal" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "avena cocinada" +msgstr[1] "avena cocinada" +msgstr[2] "avena cocinada" #. ~ Description for {'str_sp': 'cooked oatmeal'} #: data/json/items/comestibles/wheat.json @@ -93324,9 +93615,9 @@ msgstr "" #: data/json/items/comestibles/wheat.json msgid "deluxe cooked oatmeal" msgid_plural "deluxe cooked oatmeal" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "avena de lujo cocinada" +msgstr[1] "avena de lujo cocinada" +msgstr[2] "avena de lujo cocinada" #. ~ Description for {'str_sp': 'deluxe cooked oatmeal'} #: data/json/items/comestibles/wheat.json @@ -93412,6 +93703,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "galletitas" @@ -93438,9 +93730,9 @@ msgstr "Una deliciosa tarta horneada con relleno de fruta." #: data/json/items/comestibles/wheat.json msgid "cheese pizza" msgid_plural "cheese pizzas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pizza de mozzarella" +msgstr[1] "pizzas de mozzarella" +msgstr[2] "pizzas de mozzarella" #. ~ Description for cheese pizza #: data/json/items/comestibles/wheat.json @@ -93450,9 +93742,9 @@ msgstr "Una deliciosa pizza con queso derretido arriba." #: data/json/items/comestibles/wheat.json msgid "granola" msgid_plural "granola" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "granola" +msgstr[1] "granola" +msgstr[2] "granola" #. ~ Description for {'str_sp': 'granola'} #: data/json/items/comestibles/wheat.json @@ -93466,9 +93758,9 @@ msgstr "" #: data/json/items/comestibles/wheat.json msgid "maple pie" msgid_plural "maple pies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tarta de arce" +msgstr[1] "tartas de arce" +msgstr[2] "tartas de arce" #. ~ Description for maple pie #: data/json/items/comestibles/wheat.json @@ -93490,9 +93782,9 @@ msgstr "Llamados fideos ramen. Se pueden comer crudos." #: data/json/items/comestibles/wheat.json msgid "cloutie dumpling" msgid_plural "cloutie dumplings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cloutie dumpling" +msgstr[1] "cloutie dumplings" +msgstr[2] "cloutie dumplings" #. ~ Description for cloutie dumpling #: data/json/items/comestibles/wheat.json @@ -93520,9 +93812,9 @@ msgstr "" #: data/json/items/comestibles/wheat.json msgid "sponge cake" msgid_plural "sponge cakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bizcochuelo" +msgstr[1] "bizcochuelos" +msgstr[2] "bizcochuelos" #. ~ Description for sponge cake #: data/json/items/comestibles/wheat.json @@ -93532,9 +93824,9 @@ msgstr "Es una torta simple y esponjosa, típica del proletariado." #: data/json/items/comestibles/wheat.json msgid "space cake" msgid_plural "space cakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torta loca" +msgstr[1] "tortas locas" +msgstr[2] "tortas locas" #. ~ Description for space cake #: data/json/items/comestibles/wheat.json @@ -93544,9 +93836,9 @@ msgstr "El destino de esta torta es llevarte en un excelente viaje." #: data/json/items/comestibles/wheat.json msgid "brownie" msgid_plural "brownies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brownie" +msgstr[1] "brownies" +msgstr[2] "brownies" #. ~ Description for brownie #: data/json/items/comestibles/wheat.json @@ -93556,9 +93848,9 @@ msgstr "Es un brownie con mucho chocolate, igualito al que hacía tu abuela." #: data/json/items/comestibles/wheat.json msgid "'special' brownie" msgid_plural "'special' brownies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brownie 'especial'" +msgstr[1] "brownies 'especiales'" +msgstr[2] "brownies 'especiales'" #. ~ Description for {'str': "'special' brownie"} #: data/json/items/comestibles/wheat.json @@ -93959,9 +94251,9 @@ msgstr "" #: data/mods/Modular_Turrets/items.json msgid "inactive riot control turret" msgid_plural "inactive riot control turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta antidisturbios inactiva" +msgstr[1] "torretas antidisturbios inactivas" +msgstr[2] "torretas antidisturbios inactivas" #. ~ Description for {'str': 'inactive riot control turret'} #: data/json/items/corpses/inactive_bots.json @@ -94256,9 +94548,9 @@ msgstr "" #: data/json/items/corpses/inactive_bots.json msgid "inactive miner bot" msgid_plural "inactive miner bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "minerobot inactivo" +msgstr[1] "minerobots inactivos" +msgstr[2] "minerobots inactivos" #. ~ Use action friendly_msg for {'str': 'inactive miner bot'}. #: data/json/items/corpses/inactive_bots.json @@ -94308,9 +94600,9 @@ msgstr "" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive skitterbot" msgid_plural "inactive skitterbots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arañabot inactivo" +msgstr[1] "arañabots inactivos" +msgstr[2] "arañabots inactivos" #. ~ Use action friendly_msg for {'str': 'inactive skitterbot'}. #: data/json/items/corpses/inactive_bots.json @@ -95803,9 +96095,9 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "canning pot" msgid_plural "canning pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "olla de conservería" +msgstr[1] "ollas de conservería" +msgstr[2] "ollas de conservería" #. ~ Description for {'str': 'canning pot'} #: data/json/items/generic/dining_kitchen.json @@ -96032,9 +96324,9 @@ msgstr "" #: data/json/items/generic/spares.json msgid "spare parts" msgid_plural "spare parts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "partes de repuesto" +msgstr[1] "partes de repuesto" +msgstr[2] "partes de repuesto" #. ~ Description for {'str_sp': 'spare parts'} #: data/json/items/generic/spares.json @@ -96364,9 +96656,9 @@ msgstr "" #: data/json/items/generic/string.json msgid "fibrous stalk" msgid_plural "fibrous stalks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tallo fibroso" +msgstr[1] "tallos fibrosos" +msgstr[2] "tallos fibrosos" #. ~ Description for fibrous stalk #: data/json/items/generic/string.json @@ -96513,9 +96805,9 @@ msgstr "" #: data/json/items/gun/22.json msgid "Mossberg Brownie" msgid_plural "Mossberg Brownie" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Mossberg Brownie" +msgstr[1] "Mossberg Brownie" +msgstr[2] "Mossberg Brownie" #: data/json/items/gun/22.json msgid "" @@ -96530,9 +96822,9 @@ msgstr "" #: data/json/items/gun/22.json msgid "pipe rifle: .22" msgid_plural "pipe rifles: .22" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle de caño: .22" +msgstr[1] "rifles de caño: .22" +msgstr[2] "rifles de caño: .22" #: data/json/items/gun/22.json data/json/items/gun/223.json #: data/json/items/gun/3006.json data/json/items/gun/38.json @@ -96936,9 +97228,9 @@ msgstr "" #: data/json/items/gun/300.json msgid "Weatherby Mark V" msgid_plural "Weatherby Mark V" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Weatherby Mark V" +msgstr[1] "Weatherby Mark V" +msgstr[2] "Weatherby Mark V" #: data/json/items/gun/300.json msgid "" @@ -97356,9 +97648,9 @@ msgstr "" #: data/json/items/gun/32.json msgid "Walther PPK" msgid_plural "Walther PPK" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Walther PPK" +msgstr[1] "Walther PPK" +msgstr[2] "Walther PPK" #: data/json/items/gun/32.json msgid "" @@ -97385,9 +97677,9 @@ msgstr "" #: data/json/items/gun/357sig.json msgid "SIG P226" msgid_plural "SIG P226s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "SIG P226" +msgstr[1] "SIG P226" +msgstr[2] "SIG P226" #: data/json/items/gun/357sig.json msgid "" @@ -97426,9 +97718,9 @@ msgstr "" #: data/json/items/gun/36paper.json msgid "Colt M1861 Navy" msgid_plural "Colt M1861 Navy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Colt M1861 Navy" +msgstr[1] "Colt M1861 Navy" +msgstr[2] "Colt M1861 Navy" #: data/json/items/gun/36paper.json msgid "" @@ -97495,9 +97787,9 @@ msgstr[2] "" #: data/json/items/gun/38.json msgid "Ruger LCR .38" msgid_plural "Ruger LCR .38" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Ruger LCR .38" +msgstr[1] "Ruger LCR .38" +msgstr[2] "Ruger LCR .38" #: data/json/items/gun/38.json msgid "" @@ -97733,9 +98025,9 @@ msgstr "" #: data/json/items/gun/40.json msgid "handmade six-shooter" msgid_plural "handmade six-shooters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "seis-tiros casero" +msgstr[1] "seis-tiros caseros" +msgstr[2] "seis-tiros caseros" #: data/json/items/gun/40.json msgid "" @@ -97809,9 +98101,9 @@ msgstr "" #: data/json/items/gun/40x46mm.json msgid "tube 40mm launcher" msgid_plural "tube 40mm launchers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cañolanzador 40mm" +msgstr[1] "cañolanzadores 40mm" +msgstr[2] "cañolanzadores 40mm" #: data/json/items/gun/40x46mm.json msgid "" @@ -97996,9 +98288,9 @@ msgstr "" #: data/json/items/gun/44.json msgid "Henry Big Boy .44" msgid_plural "Henry Big Boy .44" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Henry Big Boy .44" +msgstr[1] "Henry Big Boy .44" +msgstr[2] "Henry Big Boy .44" #: data/json/items/gun/44.json msgid "" @@ -98020,9 +98312,9 @@ msgstr[2] "" #: data/json/items/gun/44.json msgid "Ruger Redhawk" msgid_plural "Ruger Redhawk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Ruger Redhawk" +msgstr[1] "Ruger Redhawk" +msgstr[2] "Ruger Redhawk" #: data/json/items/gun/44.json msgid "" @@ -98170,9 +98462,9 @@ msgstr "" #: data/json/items/gun/45.json msgid "pipe rifle: .45" msgid_plural "pipe rifles: .45" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle de caño: .45" +msgstr[1] "rifles de caño: .45" +msgstr[2] "rifles de caño: .45" #: data/json/items/gun/45.json msgid "Luty SMG: .45" @@ -98193,9 +98485,9 @@ msgstr "" #: data/json/items/gun/45.json msgid "homemade hand cannon" msgid_plural "homemade hand cannons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cañón de mano casero" +msgstr[1] "cañones de mano caseros" +msgstr[2] "cañones de mano caseros" #: data/json/items/gun/45.json msgid "" @@ -98227,9 +98519,9 @@ msgstr "" #: data/json/items/gun/45.json msgid "USP .45" msgid_plural "USP .45s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "USP .45" +msgstr[1] "USP .45" +msgstr[2] "USP .45" #: data/json/items/gun/45.json msgid "MK 23 MOD 0" @@ -98366,9 +98658,9 @@ msgstr "" #: data/json/items/gun/45colt.json msgid "Bond Arms Derringer" msgid_plural "Bond Arms Derringers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Revólver Bond Arms" +msgstr[1] "Revólveres Bond Arms" +msgstr[2] "Revólveres Bond Arms" #: data/json/items/gun/45colt.json msgid "" @@ -98444,9 +98736,9 @@ msgstr "" #: data/json/items/gun/50.json msgid "Barrett M107A1" msgid_plural "Barrett M107A1" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Barrett M107A1" +msgstr[1] "Barrett M107A1" +msgstr[2] "Barrett M107A1" #: data/json/items/gun/50.json msgid "" @@ -98472,9 +98764,9 @@ msgstr "" #: data/json/items/gun/50.json msgid ".50 caliber rifle" msgid_plural ".50 caliber rifles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle calibre .50" +msgstr[1] "rifles calibre .50" +msgstr[2] "rifles calibre .50" #: data/json/items/gun/50.json msgid "" @@ -98605,9 +98897,9 @@ msgstr "" #: data/json/items/gun/57.json msgid "FN Five-Seven" msgid_plural "FN Five-Sevens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "FN Five-Seven" +msgstr[1] "FN Five-Seven" +msgstr[2] "FN Five-Seven" #: data/json/items/gun/57.json msgid "" @@ -98848,9 +99140,9 @@ msgstr "" #: data/json/items/gun/762R.json msgid "Mosin-Nagant 1891/30" msgid_plural "Mosin-Nagant 1891/30" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Mosin-Nagant 1891/30" +msgstr[1] "Mosin-Nagant 1891/30" +msgstr[2] "Mosin-Nagant 1891/30" #: data/json/items/gun/762R.json msgid "" @@ -98962,9 +99254,9 @@ msgstr "" #: data/json/items/gun/8x40mm.json msgid "RM11B scout rifle" msgid_plural "RM11B scout rifles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle scout RM11B" +msgstr[1] "rifles scout RM11B" +msgstr[2] "rifles scout RM11B" #: data/json/items/gun/8x40mm.json msgid "" @@ -99123,9 +99415,9 @@ msgstr "" #: data/json/items/gun/9mm.json msgid "Cx4 Storm" msgid_plural "Cx4 Storms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cx4 Storm" +msgstr[1] "Cx4 Storm" +msgstr[2] "Cx4 Storm" #: data/json/items/gun/9mm.json msgid "" @@ -99243,9 +99535,9 @@ msgstr "" #: data/json/items/gun/9mm.json msgid "Kel-Tec SUB-2000" msgid_plural "Kel-Tec SUB-2000" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Kel-Tec SUB-2000" +msgstr[1] "Kel-Tec SUB-2000" +msgstr[2] "Kel-Tec SUB-2000" #: data/json/items/gun/9mm.json msgid "" @@ -99288,9 +99580,9 @@ msgstr "" #: data/json/items/gun/9mm.json msgid "pipe rifle: 9x19mm" msgid_plural "pipe rifles: 9x19mm" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle de caño: 9x19mm" +msgstr[1] "rifles de caño: 9x19mm" +msgstr[2] "rifles de caño: 9x19mm" #: data/json/items/gun/9mm.json msgid "Luty SMG: 9x19mm" @@ -99311,9 +99603,9 @@ msgstr "" #: data/json/items/gun/9mm.json msgid "STEN" msgid_plural "STENs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "STEN" +msgstr[1] "STEN" +msgstr[2] "STEN" #: data/json/items/gun/9mm.json msgid "" @@ -99549,9 +99841,9 @@ msgstr "" #: data/json/items/gun/9x18.json msgid "Skorpion Vz. 82" msgid_plural "Skorpion Vz. 82s" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Skorpion Vz. 82" +msgstr[1] "Skorpion Vz. 82" +msgstr[2] "Skorpion Vz. 82" #: data/json/items/gun/9x18.json msgid "" @@ -99667,9 +99959,9 @@ msgstr "" #: data/json/items/gun/combination.json msgid "pipe combination gun" msgid_plural "pipe combination guns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pistola de caño combinada" +msgstr[1] "pistolas de caño combinadas" +msgstr[2] "pistolas de caño combinadas" #: data/json/items/gun/combination.json msgid "" @@ -99833,9 +100125,9 @@ msgstr "" #: data/json/items/gun/flintlock.json msgid "flintlock carbine" msgid_plural "flintlock carbines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carabina de chispa" +msgstr[1] "carabinas de chispa" +msgstr[2] "carabinas de chispa" #: data/json/items/gun/flintlock.json msgid "" @@ -99850,9 +100142,9 @@ msgstr "" #: data/json/items/gun/flintlock.json msgid "handmade double-barrel flintlock" msgid_plural "handmade double-barrel flintlocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carabina de chispa de doble caño" +msgstr[1] "carabinas de chispa de doble caño" +msgstr[2] "carabinas de chispa de doble caño" #: data/json/items/gun/flintlock.json msgid "" @@ -99914,9 +100206,9 @@ msgstr "" #: data/json/items/gun/metal_rail.json msgid "heavy rail rifle" msgid_plural "heavy rail rifles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle pesado de riel" +msgstr[1] "rifles pesados de riel" +msgstr[2] "rifles pesados de riel" #: data/json/items/gun/metal_rail.json msgid "" @@ -100150,9 +100442,9 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Kel-Tec KSG" msgid_plural "Kel-Tec KSG" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Kel-Tec KSG" +msgstr[1] "Kel-Tec KSG" +msgstr[2] "Kel-Tec KSG" #: data/json/items/gun/shot.json msgid "" @@ -100641,9 +100933,9 @@ msgstr "" #: data/json/items/gunmod/accessories.json msgid "arrow rest" msgid_plural "arrow rests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "apoyo para flechas" +msgstr[1] "apoyos para flechas" +msgstr[2] "apoyos para flechas" #: data/json/items/gunmod/accessories.json msgid "" @@ -100696,9 +100988,9 @@ msgstr "" #: data/json/items/gunmod/accessories.json msgid "bow dampening kit" msgid_plural "bow dampening kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "equipo de amortiguación de arco" +msgstr[1] "equipos de amortiguación de arco" +msgstr[2] "equipos de amortiguación de arco" #: data/json/items/gunmod/accessories.json msgid "" @@ -100764,9 +101056,9 @@ msgstr "" #: data/json/items/gunmod/barrel.json msgid "shortened barrel" msgid_plural "shortened barrels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cañón recortado" +msgstr[1] "cañones recortados" +msgstr[2] "cañones recortados" #: data/json/items/gunmod/barrel.json msgid "" @@ -100786,9 +101078,9 @@ msgstr "cañón" #: data/json/items/gunmod/barrel.json msgid "upstest" msgid_plural "upstests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "upstest" +msgstr[1] "upstests" +msgstr[2] "upstests" #: data/json/items/gunmod/barrel.json msgid "" @@ -100819,9 +101111,9 @@ msgstr "bajocañón" #: data/json/items/gunmod/brass_catcher.json msgid "brass catcher" msgid_plural "brass catchers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "recolector de latón" +msgstr[1] "recolectores de latón" +msgstr[2] "recolectores de latón" #: data/json/items/gunmod/brass_catcher.json msgid "" @@ -100875,9 +101167,9 @@ msgstr "" #: data/json/items/gunmod/grip.json msgid "lightweight replacement furniture" msgid_plural "lightweight replacement furnitures" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "accesorio liviano de reemplazo" +msgstr[1] "accesorios livianos de reemplazo" +msgstr[2] "accesorios livianos de reemplazo" #: data/json/items/gunmod/grip.json msgid "" @@ -101022,9 +101314,9 @@ msgstr "" #: data/json/items/gunmod/mechanism.json msgid "match trigger" msgid_plural "match triggers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gatillo balanceado" +msgstr[1] "gatillos balanceados" +msgstr[2] "gatillos balanceados" #: data/json/items/gunmod/mechanism.json msgid "" @@ -101041,9 +101333,9 @@ msgstr "mecanismo" #: data/json/items/gunmod/mechanism.json msgid "drop-in auto sear" msgid_plural "drop-in auto sears" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sear para automático" +msgstr[1] "sears para automático" +msgstr[2] "sears para automático" #: data/json/items/gunmod/mechanism.json msgid "" @@ -101056,9 +101348,9 @@ msgstr "" #: data/json/items/gunmod/mechanism.json msgid "lightning link" msgid_plural "lightning links" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "unión ráfaga" +msgstr[1] "uniones ráfaga" +msgstr[2] "uniones ráfaga" #: data/json/items/gunmod/mechanism.json msgid "" @@ -101232,9 +101524,9 @@ msgstr "bocacha" #: data/json/items/gunmod/muzzle.json msgid "muzzle brake" msgid_plural "muzzle brakes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "freno de boca" +msgstr[1] "frenos de boca" +msgstr[2] "frenos de boca" #: data/json/items/gunmod/muzzle.json msgid "" @@ -101318,9 +101610,9 @@ msgstr "" #: data/json/items/gunmod/muzzle.json msgid "RK6S34 suppressor" msgid_plural "RK6S34 suppressors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "silenciador RK6S34" +msgstr[1] "silenciadores RK6S34" +msgstr[2] "silenciadores RK6S34" #: data/json/items/gunmod/muzzle.json msgid "" @@ -101335,9 +101627,9 @@ msgstr "" #: data/json/items/gunmod/muzzle.json msgid "shotgun suppressor" msgid_plural "shotgun suppressors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "silenciador de escopeta" +msgstr[1] "silenciadores de escopeta" +msgstr[2] "silenciadores de escopeta" #: data/json/items/gunmod/muzzle.json msgid "" @@ -101382,9 +101674,9 @@ msgstr "" #: data/json/items/gunmod/muzzle.json msgid "compact suppressor" msgid_plural "compact suppressors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "silenciador compacto" +msgstr[1] "silenciadores compactos" +msgstr[2] "silenciadores compactos" #: data/json/items/gunmod/muzzle.json msgid "" @@ -101397,9 +101689,9 @@ msgstr "" #: data/json/items/gunmod/rail.json data/mods/No_Hope/Items/gunmods.json msgid "rail-mounted crossbow" msgid_plural "rail-mounted crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ballesta montable de riel" +msgstr[1] "ballestas montables de riel" +msgstr[2] "ballestas montables de riel" #: data/json/items/gunmod/rail.json data/mods/No_Hope/Items/gunmods.json msgid "" @@ -101463,9 +101755,9 @@ msgstr "" #: data/json/items/gunmod/rail.json msgid "offset sight rail" msgid_plural "offset sight rails" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ranura para mirilla de compensación" +msgstr[1] "ranuras para mirilla de compensación" +msgstr[2] "ranuras para mirilla de compensación" #: data/json/items/gunmod/rail.json msgid "An additional rail set at 45° for attaching a secondary optic." @@ -101537,9 +101829,9 @@ msgstr "" #: data/json/items/gunmod/sights.json msgid "five pin bow sight" msgid_plural "five pin bow sights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mirilla de cinco pines para arco" +msgstr[1] "mirillas de cinco pines para arco" +msgstr[2] "mirillas de cinco pines para arco" #: data/json/items/gunmod/sights.json msgid "" @@ -101559,9 +101851,9 @@ msgstr "miras" #: data/json/items/gunmod/sights.json msgid "single pin bow sight" msgid_plural "single pin bow sights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mirilla de un pin para arco" +msgstr[1] "mirillas de un pin para arco" +msgstr[2] "mirillas de un pin para arco" #: data/json/items/gunmod/sights.json msgid "" @@ -101720,9 +102012,9 @@ msgstr "" #: data/json/items/gunmod/sights.json msgid "telescopic sight" msgid_plural "telescopic sights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mira telescópica" +msgstr[1] "miras telescópicas" +msgstr[2] "miras telescópicas" #: data/json/items/gunmod/sights.json msgid "" @@ -101734,9 +102026,9 @@ msgstr "" #: data/json/items/gunmod/sights.json msgid "telescopic pistol sight" msgid_plural "telescopic pistol sights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mira telescópica de pistola" +msgstr[1] "miras telescópicas de pistola" +msgstr[2] "miras telescópicas de pistola" #: data/json/items/gunmod/sights.json msgid "" @@ -101768,9 +102060,9 @@ msgstr "honda" #: data/json/items/gunmod/stock.json msgid "adjustable stock" msgid_plural "adjustable stocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "culata ajustable" +msgstr[1] "culatas ajustables" +msgstr[2] "culatas ajustables" #: data/json/items/gunmod/stock.json msgid "An adjustable replacement stock improving both recoil and accuracy." @@ -101838,9 +102130,9 @@ msgstr "Un reemplazo diseñado para absorber el retroceso percibido." #: data/json/items/gunmod/stock.json msgid "cheek pad" msgid_plural "cheek pads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "almohadilla de mejilla" +msgstr[1] "almohadillas de mejilla" +msgstr[2] "almohadillas de mejilla" #: data/json/items/gunmod/stock.json msgid "" @@ -101919,9 +102211,9 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "pipe combination gun shotgun" msgid_plural "pipe combination gun shotguns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "escopeta de caño combinada" +msgstr[1] "escopetas de caño combinadas" +msgstr[2] "escopetas de caño combinadas" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -101934,9 +102226,9 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "forward grip" msgid_plural "forward grips" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mango vertical" +msgstr[1] "mangos verticales" +msgstr[2] "mangos verticales" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -101964,9 +102256,9 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "integrated bayonet" msgid_plural "integrated bayonets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bayoneta integrada" +msgstr[1] "bayonetas integradas" +msgstr[2] "bayonetas integradas" #: data/json/items/gunmod/underbarrel.json msgid "This is the bayonet integrated in the firearm." @@ -102187,9 +102479,9 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "40mm pipe launcher" msgid_plural "40mm pipe launchers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caño lanzador 40mm" +msgstr[1] "caños lanzadores 40mm" +msgstr[2] "caños lanzadores 40mm" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -102248,9 +102540,9 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "underslung shotgun" msgid_plural "underslung shotguns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "escopeta colgante" +msgstr[1] "escopetas colgantes" +msgstr[2] "escopetas colgantes" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -105451,9 +105743,9 @@ msgstr "" #: data/json/items/melee/bludgeons.json msgid "L-stick (off)" msgid_plural "L-sticks (off)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Palo-L (apag.)" +msgstr[1] "Palos-L (apag.)" +msgstr[2] "Palos-L (apag.)" #. ~ Use action msg for {'str': 'L-stick (off)', 'str_pl': 'L-sticks (off)'}. #: data/json/items/melee/bludgeons.json @@ -106338,9 +106630,9 @@ msgstr "" #: data/json/items/melee/spears_and_polearms.json msgid "homemade halfpike" msgid_plural "homemade halfpikes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "espontón casero" +msgstr[1] "espontones caseros" +msgstr[2] "espontones caseros" #. ~ Description for {'str': 'homemade halfpike'} #: data/json/items/melee/spears_and_polearms.json @@ -106367,9 +106659,9 @@ msgstr "" #: data/json/items/melee/spears_and_polearms.json msgid "pipe spear" msgid_plural "pipe spears" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caño lanza" +msgstr[1] "caños lanza" +msgstr[2] "caños lanza" #. ~ Description for {'str': 'pipe spear'} #: data/json/items/melee/spears_and_polearms.json @@ -106772,9 +107064,9 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "folding knife" msgid_plural "folding knives" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cuchillo plegable" +msgstr[1] "cuchillos plegables" +msgstr[2] "cuchillos plegables" #. ~ Description for {'str': 'folding knife', 'str_pl': 'folding knives'} #: data/json/items/melee/swords_and_blades.json @@ -108002,9 +108294,9 @@ msgstr "" #: data/mods/No_Hope/Items/swords_and_blades.json msgid "electric chainsaw lajatang (off)" msgid_plural "electric chainsaw lajatangs (off)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motosierra lajatang eléctrica (apag.)" +msgstr[1] "motosierras lajatang eléctricas (apag.)" +msgstr[2] "motosierras lajatang eléctricas (apag.)" #. ~ Description for {'str': 'electric chainsaw lajatang (off)', 'str_pl': #. 'electric chainsaw lajatangs (off)'} @@ -108024,9 +108316,9 @@ msgstr "" #: data/mods/No_Hope/Items/swords_and_blades.json msgid "electric chainsaw lajatang (on)" msgid_plural "electric chainsaw lajatangs (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motosierra lajatang eléctrica (enc.)" +msgstr[1] "motosierras lajatang eléctricas (enc.)" +msgstr[2] "motosierras lajatang eléctricas (enc.)" #. ~ Description for {'str': 'electric chainsaw lajatang (on)', 'str_pl': #. 'electric chainsaw lajatangs (on)'} @@ -108181,9 +108473,9 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "electric combat chainsaw (on)" msgid_plural "electric combat chainsaws (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motosierra eléctrica de combate (enc.)" +msgstr[1] "motosierras eléctricas de combate (enc.)" +msgstr[2] "motosierras eléctricas de combate (enc.)" #. ~ Description for {'str': 'electric combat chainsaw (on)', 'str_pl': #. 'electric combat chainsaws (on)'} @@ -108370,9 +108662,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "crude wooden arrow" msgid_plural "crude wooden arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha rudimentaria de madera" +msgstr[1] "flechas rudimentarias de madera" +msgstr[2] "flechas rudimentarias de madera" #. ~ Description for {'str': 'crude wooden arrow'} #: data/json/items/ranged/archery.json @@ -108386,9 +108678,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "wooden bodkin arrow" msgid_plural "wooden bodkin arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha bodkin de madera" +msgstr[1] "flechas bodkin de madera" +msgstr[2] "flechas bodkin de madera" #. ~ Description for {'str': 'wooden bodkin arrow'} #: data/json/items/ranged/archery.json @@ -108402,9 +108694,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "wooden rubber blunt arrow" msgid_plural "wooden rubber blunt arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de madera con punta de goma" +msgstr[1] "flechas de madera con punta de goma" +msgstr[2] "flechas de madera con punta de goma" #. ~ Description for {'str': 'wooden rubber blunt arrow'} #: data/json/items/ranged/archery.json @@ -108419,9 +108711,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "simple wooden small game arrow" msgid_plural "simple wooden small game arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha simple de caza menor de madera" +msgstr[1] "flechas simples de caza menor de madera" +msgstr[2] "flechas simples de caza menor de madera" #. ~ Description for {'str': 'simple wooden small game arrow'} #: data/json/items/ranged/archery.json @@ -108437,9 +108729,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "wooden broadhead arrow" msgid_plural "wooden broadhead arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de madera de punta ancha" +msgstr[1] "flechas de madera de punta ancha" +msgstr[2] "flechas de madera de punta ancha" #. ~ Description for {'str': 'wooden broadhead arrow'} #: data/json/items/ranged/archery.json @@ -108471,9 +108763,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "wooden small game arrow" msgid_plural "wooden small game arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de caza menor de madera" +msgstr[1] "flechas de caza menor de madera" +msgstr[2] "flechas de caza menor de madera" #. ~ Description for {'str': 'wooden small game arrow'} #: data/json/items/ranged/archery.json @@ -108505,9 +108797,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "simple metal arrow" msgid_plural "simple metal arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha común de metal" +msgstr[1] "flechas comunes de metal" +msgstr[2] "flechas comunes de metal" #. ~ Description for {'str': 'simple metal arrow'} #: data/json/items/ranged/archery.json @@ -108521,9 +108813,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "aluminum broadhead arrow" msgid_plural "aluminum broadhead arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de aluminio de punta ancha" +msgstr[1] "flechas de aluminio de punta ancha" +msgstr[2] "flechas de aluminio de punta ancha" #. ~ Description for {'str': 'aluminum broadhead arrow'} #: data/json/items/ranged/archery.json @@ -108538,9 +108830,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "aluminum field point arrow" msgid_plural "aluminum field point arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de aluminio con punta de campo" +msgstr[1] "flechas de aluminio con punta de campo" +msgstr[2] "flechas de aluminio con punta de campo" #. ~ Description for {'str': 'aluminum field point arrow'} #: data/json/items/ranged/archery.json @@ -108554,9 +108846,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "aluminum small game arrow" msgid_plural "aluminum small game arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de aluminio de caza menor" +msgstr[1] "flechas de aluminio de caza menor" +msgstr[2] "flechas de aluminio de caza menor" #. ~ Description for {'str': 'aluminum small game arrow'} #: data/json/items/ranged/archery.json @@ -108572,9 +108864,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "carbon fiber hunting arrow" msgid_plural "carbon fiber hunting arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de fibra de carbono de caza" +msgstr[1] "flechas de fibra de carbono de caza" +msgstr[2] "flechas de fibra de carbono de caza" #. ~ Description for {'str': 'carbon fiber hunting arrow'} #: data/json/items/ranged/archery.json @@ -108590,9 +108882,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "explosive arrow" msgid_plural "explosive arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha explosiva" +msgstr[1] "flechas explosivas" +msgstr[2] "flechas explosivas" #. ~ Description for {'str': 'explosive arrow'} #: data/json/items/ranged/archery.json @@ -108691,9 +108983,9 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "compound bow (high)" msgid_plural "compound bows (high)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arco de poleas (alta)" +msgstr[1] "arcos de poleas (alta)" +msgstr[2] "arcos de poleas (alta)" #: data/json/items/ranged/archery.json msgid "" @@ -108799,9 +109091,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "crude wooden bolt" msgid_plural "crude wooden bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno rudimentario de madera" +msgstr[1] "pernos rudimentarios de madera" +msgstr[2] "pernos rudimentarios de madera" #. ~ Description for {'str': 'crude wooden bolt'} #: data/json/items/ranged/crossbows.json @@ -108831,9 +109123,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "simple wooden small game bolt" msgid_plural "simple wooden small game bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno simple de caza menor de madera" +msgstr[1] "pernos simples de caza menor de madera" +msgstr[2] "pernos simples de caza menor de madera" #. ~ Description for {'str': 'simple wooden small game bolt'} #: data/json/items/ranged/crossbows.json @@ -108865,9 +109157,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "wooden broadhead bolt" msgid_plural "wooden broadhead bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno de madera de punta ancha" +msgstr[1] "pernos de madera de punta ancha" +msgstr[2] "pernos de madera de punta ancha" #. ~ Description for {'str': 'wooden broadhead bolt'} #: data/json/items/ranged/crossbows.json @@ -108882,9 +109174,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "wooden bodkin bolt" msgid_plural "wooden bodkin bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno bodkin de madera" +msgstr[1] "pernos bodkin de madera" +msgstr[2] "pernos bodkin de madera" #. ~ Description for {'str': 'wooden bodkin bolt'} #: data/json/items/ranged/crossbows.json @@ -108898,9 +109190,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "wooden small game bolt" msgid_plural "wooden small game bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno de caza menor de madera" +msgstr[1] "pernos de caza menor de madera" +msgstr[2] "pernos de caza menor de madera" #. ~ Description for {'str': 'wooden small game bolt'} #: data/json/items/ranged/crossbows.json @@ -108916,9 +109208,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "simple metal bolt" msgid_plural "simple metal bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno simple de metal" +msgstr[1] "pernos simples de metal" +msgstr[2] "pernos simples de metal" #. ~ Description for {'str': 'simple metal bolt'} #: data/json/items/ranged/crossbows.json @@ -108932,9 +109224,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "aluminum broadhead bolt" msgid_plural "aluminum broadhead bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno de aluminio de punta ancha" +msgstr[1] "pernos de aluminio de punta ancha" +msgstr[2] "pernos de aluminio de punta ancha" #. ~ Description for {'str': 'aluminum broadhead bolt'} #: data/json/items/ranged/crossbows.json @@ -108948,9 +109240,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "aluminum field point bolt" msgid_plural "aluminum field point bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno de aluminio con punta de campo" +msgstr[1] "pernos de aluminio con punta de campo" +msgstr[2] "pernos de aluminio con punta de campo" #. ~ Description for {'str': 'aluminum field point bolt'} #: data/json/items/ranged/crossbows.json @@ -108964,9 +109256,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "aluminum small game bolt" msgid_plural "aluminum small game bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno de aluminio de caza menor" +msgstr[1] "pernos de aluminio de caza menor" +msgstr[2] "pernos de aluminio de caza menor" #. ~ Description for {'str': 'aluminum small game bolt'} #: data/json/items/ranged/crossbows.json @@ -108982,9 +109274,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "carbon fiber hunting bolt" msgid_plural "carbon fiber hunting bolts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perno de fibra de carbono de caza" +msgstr[1] "pernos de fibra de carbono de caza" +msgstr[2] "pernos de fibra de carbono de caza" #. ~ Description for {'str': 'carbon fiber hunting bolt'} #: data/json/items/ranged/crossbows.json @@ -109018,9 +109310,9 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "bullet crossbow" msgid_plural "bullet crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ballesta para piedras" +msgstr[1] "ballestas para piedras" +msgstr[2] "ballestas para piedras" #: data/json/items/ranged/crossbows.json msgid "" @@ -109138,9 +109430,9 @@ msgstr "" #: data/json/items/ranged/pneumatic.json msgid "BB gun" msgid_plural "BB guns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle de balines" +msgstr[1] "rifles de balines" +msgstr[2] "rifles de balines" #: data/json/items/ranged/pneumatic.json msgid "" @@ -109223,9 +109515,9 @@ msgstr "" #: data/json/items/ranged/slings.json msgid "brace slingshot" msgid_plural "brace slingshots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gomera con soporte" +msgstr[1] "gomeras con soporte" +msgstr[2] "gomeras con soporte" #: data/json/items/ranged/slings.json msgid "" @@ -109358,9 +109650,9 @@ msgstr "" #: data/json/items/ranged/throwing.json msgid "bolas" msgid_plural "bolases" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "boleadoras" +msgstr[1] "boleadoras" +msgstr[2] "boleadoras" #. ~ Description for {'str': 'bolas', 'str_pl': 'bolases'} #: data/json/items/ranged/throwing.json @@ -109403,9 +109695,9 @@ msgstr "Un frisbee de plástico hecho para juegos al aire libre." #: data/json/items/ranged/throwing.json msgid "net" msgid_plural "nets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "red" +msgstr[1] "redes" +msgstr[2] "redes" #. ~ Description for {'str': 'net'} #: data/json/items/ranged/throwing.json @@ -109463,9 +109755,9 @@ msgstr "" #: data/json/items/ranged/throwing.json msgid "throwing stick" msgid_plural "throwing sticks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "palo arrojadizo" +msgstr[1] "palos arrojadizos" +msgstr[2] "palos arrojadizos" #. ~ Description for {'str': 'throwing stick'} #: data/json/items/ranged/throwing.json @@ -109509,9 +109801,9 @@ msgstr "" #: data/json/items/resources/chemicals.json msgid "potassium alum" msgid_plural "potassium alums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "alumbre potásico" +msgstr[1] "alumbre potásico" +msgstr[2] "alumbre potásico" #. ~ Description for {'str': 'potassium alum'} #: data/json/items/resources/chemicals.json @@ -109530,9 +109822,9 @@ msgstr "" #: data/json/items/resources/chemicals.json msgid "cloth dye powder" msgid_plural "cloth dye powders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "polvo para teñir lana" +msgstr[1] "polvo para teñir lana" +msgstr[2] "polvo para teñir lana" #. ~ Description for {'str': 'cloth dye powder'} #: data/json/items/resources/chemicals.json @@ -109546,9 +109838,9 @@ msgstr "" #: data/json/items/resources/fasteners.json msgid "steel buckle" msgid_plural "steel buckles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hebilla de acero" +msgstr[1] "hebillas de acero" +msgstr[2] "hebillas de acero" #. ~ Description for {'str': 'steel buckle'} #: data/json/items/resources/fasteners.json @@ -109558,9 +109850,9 @@ msgstr "Es una hebilla de acero, como la que tienen los cinturones." #: data/json/items/resources/fasteners.json msgid "plastic button" msgid_plural "plastic buttons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "botón plástico" +msgstr[1] "botones plásticos" +msgstr[2] "botones plásticos" #. ~ Description for {'str': 'plastic button'} #: data/json/items/resources/fasteners.json @@ -109570,9 +109862,9 @@ msgstr "Es un botón de plástico, como el que se usa en mucha ropa." #: data/json/items/resources/fasteners.json msgid "steel button" msgid_plural "steel buttons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "botón de acero" +msgstr[1] "botones de acero" +msgstr[2] "botones de acero" #. ~ Description for {'str': 'steel button'} #: data/json/items/resources/fasteners.json @@ -109582,9 +109874,9 @@ msgstr "Es un botón de acero, como el que se usa en mucha ropa." #: data/json/items/resources/fasteners.json msgid "wooden button" msgid_plural "wooden buttons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "botón de madera" +msgstr[1] "botones de madera" +msgstr[2] "botones de madera" #. ~ Description for {'str': 'wooden button'} #: data/json/items/resources/fasteners.json @@ -109595,9 +109887,9 @@ msgstr "" #: data/json/items/resources/fasteners.json msgid "steel snap fastener" msgid_plural "steel snap fasteners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "broche metálico de acero" +msgstr[1] "broches metálicos de acero" +msgstr[2] "broches metálicos de acero" #. ~ Description for {'str': 'steel snap fastener'} #: data/json/items/resources/fasteners.json @@ -109608,9 +109900,9 @@ msgstr "" #: data/json/items/resources/fasteners.json msgid "touch fastener" msgid_plural "touch fasteners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cierre abrojo" +msgstr[1] "cierres abrojo" +msgstr[2] "cierres abrojo" #. ~ Description for {'str': 'touch fastener'} #: data/json/items/resources/fasteners.json @@ -109624,9 +109916,9 @@ msgstr "" #: data/json/items/resources/fasteners.json msgid "long plastic zipper" msgid_plural "long plastic zippers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cierre grande de plástico" +msgstr[1] "cierres grandes de plástico" +msgstr[2] "cierres grandes de plástico" #. ~ Description for {'str': 'long plastic zipper'} #: data/json/items/resources/fasteners.json @@ -109636,9 +109928,9 @@ msgstr "Es un cierre grande de plástico, como el que se usa en mucha ropa." #: data/json/items/resources/fasteners.json msgid "short plastic zipper" msgid_plural "short plastic zippers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cierre chico de plástico" +msgstr[1] "cierres chicos de plástico" +msgstr[2] "cierres chicos de plástico" #. ~ Description for {'str': 'short plastic zipper'} #: data/json/items/resources/fasteners.json @@ -109968,9 +110260,9 @@ msgstr[2] "platino" #: data/json/items/resources/metal.json msgid "zinc" msgid_plural "zinc" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zinc" +msgstr[1] "zinc" +msgstr[2] "zinc" #. ~ Description for {'str_sp': 'zinc'} #: data/json/items/resources/metal.json @@ -110036,9 +110328,9 @@ msgstr "" #: data/json/items/resources/metal.json msgid "small metal sheet" msgid_plural "small metal sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lámina pequeña de metal" +msgstr[1] "láminas pequeñas de metal" +msgstr[2] "láminas pequeñas de metal" #. ~ Description for {'str': 'small metal sheet'} #: data/json/items/resources/metal.json @@ -110076,9 +110368,9 @@ msgstr "Es un pedazo pesado de acero, útil para fabricar algunas cosas." #: data/json/items/resources/metal.json msgid "door hinge" msgid_plural "door hinges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bisagra de puerta" +msgstr[1] "bisagras de puerta" +msgstr[2] "bisagras de puerta" #. ~ Description for {'str': 'door hinge'} #: data/json/items/resources/metal.json @@ -110215,9 +110507,9 @@ msgstr "" #: data/json/items/resources/misc.json msgid "fuse" msgid_plural "fuse" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mecha" +msgstr[1] "mecha" +msgstr[2] "mecha" #. ~ Description for {'str_sp': 'fuse'} #: data/json/items/resources/misc.json @@ -110349,9 +110641,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "cotton scraps" msgid_plural "cotton scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de algodón" +msgstr[1] "pedazos de algodón" +msgstr[2] "pedazos de algodón" #. ~ Description for {'str_sp': 'cotton scraps'} #: data/json/items/resources/tailoring.json @@ -110367,9 +110659,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "faux fur scraps" msgid_plural "faux fur scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de piel artificial" +msgstr[1] "pedazos de piel artificial" +msgstr[2] "pedazos de piel artificial" #. ~ Description for {'str_sp': 'faux fur scraps'} #: data/json/items/resources/tailoring.json @@ -110383,9 +110675,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "felt scraps" msgid_plural "felt scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trozos de fieltro" +msgstr[1] "trozos de fieltro" +msgstr[2] "trozos de fieltro" #. ~ Description for {'str_sp': 'felt scraps'} #: data/json/items/resources/tailoring.json @@ -110401,9 +110693,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "fur scraps" msgid_plural "fur scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de piel" +msgstr[1] "pedazos de piel" +msgstr[2] "pedazos de piel" #. ~ Description for {'str_sp': 'fur scraps'} #: data/json/items/resources/tailoring.json @@ -110417,9 +110709,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "Kevlar scraps" msgid_plural "Kevlar scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de Kevlar" +msgstr[1] "pedazos de Kevlar" +msgstr[2] "pedazos de Kevlar" #. ~ Description for {'str_sp': 'Kevlar scraps'} #: data/json/items/resources/tailoring.json @@ -110437,9 +110729,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "leather scraps" msgid_plural "leather scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de cuero" +msgstr[1] "pedazos de cuero" +msgstr[2] "pedazos de cuero" #. ~ Description for {'str_sp': 'leather scraps'} #: data/json/items/resources/tailoring.json @@ -110453,9 +110745,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "neoprene scraps" msgid_plural "neoprene scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de neopreno" +msgstr[1] "pedazos de neopreno" +msgstr[2] "pedazos de neopreno" #. ~ Description for {'str_sp': 'neoprene scraps'} #: data/json/items/resources/tailoring.json @@ -110469,9 +110761,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "synthetic fabric scraps" msgid_plural "synthetic fabric scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de tela sintética" +msgstr[1] "pedazos de tela sintética" +msgstr[2] "pedazos de tela sintética" #. ~ Description for {'str_sp': 'synthetic fabric scraps'} #: data/json/items/resources/tailoring.json @@ -110485,9 +110777,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "Nomex scraps" msgid_plural "Nomex scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trozos de Nomex" +msgstr[1] "trozos de Nomex" +msgstr[2] "trozos de Nomex" #. ~ Description for {'str_sp': 'Nomex scraps'} #: data/json/items/resources/tailoring.json @@ -110505,9 +110797,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "cotton sheet" msgid_plural "cotton sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela de algodón" +msgstr[1] "telas de algodón" +msgstr[2] "telas de algodón" #. ~ Description for {'str': 'cotton sheet'} #: data/json/items/resources/tailoring.json @@ -110517,9 +110809,9 @@ msgstr "Es una tela de algodón, ideal para hacer ropa." #: data/json/items/resources/tailoring.json msgid "patchwork cotton clothing parts" msgid_plural "patchwork cotton clothing parts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "retazos de ropa de algodón" +msgstr[1] "retazos de ropa de algodón" +msgstr[2] "retazos de ropa de algodón" #. ~ Description for {'str_sp': 'patchwork cotton clothing parts'} #: data/json/items/resources/tailoring.json @@ -110535,9 +110827,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "faux fur sheet" msgid_plural "faux fur sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela de piel artificial" +msgstr[1] "telas de piel artificial" +msgstr[2] "telas de piel artificial" #. ~ Description for {'str': 'faux fur sheet'} #: data/json/items/resources/tailoring.json @@ -110547,9 +110839,9 @@ msgstr "Es una tela colorida de piel artificial, ideal para hacer ropa." #: data/json/items/resources/tailoring.json msgid "patchwork faux fur clothing parts" msgid_plural "patchwork faux fur clothing parts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "retazos de ropa de piel artificial" +msgstr[1] "retazos de ropa de piel artificial" +msgstr[2] "retazos de ropa de piel artificial" #. ~ Description for {'str_sp': 'patchwork faux fur clothing parts'} #: data/json/items/resources/tailoring.json @@ -110565,9 +110857,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "felt sheet" msgid_plural "felt sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela de fieltro" +msgstr[1] "telas de fieltro" +msgstr[2] "telas de fieltro" #. ~ Description for {'str': 'felt sheet'} #: data/json/items/resources/tailoring.json @@ -110595,9 +110887,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "Kevlar sheet" msgid_plural "Kevlar sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela de Kevlar" +msgstr[1] "telas de Kevlar" +msgstr[2] "telas de Kevlar" #. ~ Description for {'str': 'Kevlar sheet'} #: data/json/items/resources/tailoring.json @@ -110611,9 +110903,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "neoprene sheet" msgid_plural "neoprene sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela de neopreno" +msgstr[1] "telas de neopreno" +msgstr[2] "telas de neopreno" #. ~ Description for {'str': 'neoprene sheet'} #: data/json/items/resources/tailoring.json @@ -110646,9 +110938,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "Nomex sheet" msgid_plural "Nomex sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela de Nomex" +msgstr[1] "telas de Nomex" +msgstr[2] "telas de Nomex" #. ~ Description for {'str': 'Nomex sheet'} #: data/json/items/resources/tailoring.json @@ -110661,9 +110953,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "patchwork Nomex clothing parts" msgid_plural "patchwork Nomex clothing parts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "retazos de ropa de Nomex" +msgstr[1] "retazos de ropa de Nomex" +msgstr[2] "retazos de ropa de Nomex" #. ~ Description for {'str_sp': 'patchwork Nomex clothing parts'} #: data/json/items/resources/tailoring.json @@ -110679,9 +110971,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "synthetic fabric sheet" msgid_plural "synthetic fabric sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela sintética" +msgstr[1] "telas sintética" +msgstr[2] "telas sintética" #. ~ Description for {'str': 'synthetic fabric sheet'} #: data/json/items/resources/tailoring.json @@ -110691,9 +110983,9 @@ msgstr "Es una tela sintética, ideal para hacer ropa." #: data/json/items/resources/tailoring.json msgid "patchwork synthetic fabric clothing parts" msgid_plural "patchwork synthetic fabric clothing parts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "retazos de ropa de tela sintética" +msgstr[1] "retazos de ropa de tela sintética" +msgstr[2] "retazos de ropa de tela sintética" #. ~ Description for {'str_sp': 'patchwork synthetic fabric clothing parts'} #: data/json/items/resources/tailoring.json @@ -110709,9 +111001,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "Kevlar thread" msgid_plural "Kevlar threads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hilo de Kevlar" +msgstr[1] "hilos de Kevlar" +msgstr[2] "hilos de Kevlar" #. ~ Description for {'str': 'Kevlar thread'} #: data/json/items/resources/tailoring.json @@ -110729,9 +111021,9 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "Nomex thread" msgid_plural "Nomex threads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hilo de Nomex" +msgstr[1] "hilos de Nomex" +msgstr[2] "hilos de Nomex" #. ~ Description for {'str': 'Nomex thread'} #: data/json/items/resources/tailoring.json @@ -111285,9 +111577,9 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "sealed jar of eggs" msgid_plural "sealed jars of eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "frasco sellado con huevos" +msgstr[1] "frascos sellados con huevos" +msgstr[2] "frascos sellados con huevos" #. ~ Use action menu_text for {'str': 'sealed jar of eggs', 'str_pl': 'sealed #. jars of eggs'}. @@ -111322,9 +111614,9 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "sealed jar of pickles" msgid_plural "sealed jars of pickles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "frasco sellado con pickles" +msgstr[1] "frascos sellados con pickles" +msgstr[2] "frascos sellados con pickles" #. ~ Description for {'str': 'sealed jar of pickles', 'str_pl': 'sealed jars #. of pickles'} @@ -111518,9 +111810,9 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "fermenting pickle jar" msgid_plural "fermenting pickle jars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "frasco de pickles fermentando" +msgstr[1] "frascos de pickles fermentando" +msgstr[2] "frascos de pickles fermentando" #. ~ Use action msg for {'str': 'fermenting pickle jar'}. #. ~ Use action msg for {'str': 'fermenting sauerkraut jar'}. @@ -111566,9 +111858,9 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "pressure cooker" msgid_plural "pressure cookers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "olla a presión" +msgstr[1] "ollas a presión" +msgstr[2] "ollas a presión" #. ~ Description for {'str': 'pressure cooker'} #: data/json/items/tool/cooking.json @@ -111990,9 +112282,9 @@ msgstr "" #: data/json/items/tool/electronics.json msgid "e-ink tablet PC" msgid_plural "e-ink tablet PCs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lector electrónico" +msgstr[1] "lectores electrónicos" +msgstr[2] "lectores electrónicos" #. ~ Description for {'str': 'e-ink tablet PC'} #: data/json/items/tool/electronics.json @@ -115162,9 +115454,9 @@ msgstr "" #: data/json/items/tool/metalworking.json msgid "bronze anvil" msgid_plural "bronze anvils" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "yunque de bronce" +msgstr[1] "yunques de bronce" +msgstr[2] "yunques de bronce" #. ~ Description for {'str': 'bronze anvil'} #: data/json/items/tool/metalworking.json @@ -115350,9 +115642,9 @@ msgstr "" #: data/json/items/tool/metalworking.json msgid "chainmail sheet" msgid_plural "chainmail sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "plancha de cota de malla" +msgstr[1] "planchas de cota de malla" +msgstr[2] "planchas de cota de malla" #. ~ Description for {'str': 'chainmail sheet'} #: data/json/items/tool/metalworking.json @@ -116864,9 +117156,9 @@ msgstr "" #: data/json/items/tool/science.json msgid "basic laboratory analysis kit" msgid_plural "basic laboratory analysis kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "equipo básico de análisis de laboratorio" +msgstr[1] "equipos básicos de análisis de laboratorio" +msgstr[2] "equipos básicos de análisis de laboratorio" #. ~ Description for {'str': 'basic laboratory analysis kit'} #: data/json/items/tool/science.json @@ -116919,9 +117211,9 @@ msgstr "" #: data/json/items/tool/science.json msgid "pH meter" msgid_plural "pH meters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "medidor de pH" +msgstr[1] "medidores de pH" +msgstr[2] "medidores de pH" #. ~ Description for {'str': 'pH meter'} #: data/json/items/tool/science.json @@ -118437,9 +118729,9 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "electric kiln" msgid_plural "electric kilns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fosas de carbonización eléctricas" +msgstr[1] "fosa de carbonización eléctrica" +msgstr[2] "fosa de carbonización eléctrica" #. ~ Description for {'str': 'electric kiln'} #: data/json/items/tool/workshop.json @@ -119381,9 +119673,9 @@ msgstr "" #: data/json/items/vehicle/cargo.json msgid "cargo lock set" msgid_plural "cargo lock sets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bloqueo para puerta de carga" +msgstr[1] "bloqueos para puerta de carga" +msgstr[2] "bloqueos para puerta de carga" #. ~ Description for {'str': 'cargo lock set'} #: data/json/items/vehicle/cargo.json @@ -119452,9 +119744,9 @@ msgstr "" #: data/json/items/vehicle/cargo.json msgid "livestock carrier" msgid_plural "livestock carriers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "transportador de ganado" +msgstr[1] "transportadores de ganado" +msgstr[2] "transportadores de ganado" #. ~ Description for {'str': 'livestock carrier'} #: data/json/items/vehicle/cargo.json @@ -119598,9 +119890,9 @@ msgstr "" #: data/json/vehicleparts/vehicle_parts.json msgid "electronics control unit" msgid_plural "electronics control units" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "unidad electrónica de control" +msgstr[1] "unidades electrónicas de control" +msgstr[2] "unidades electrónicas de control" #: data/json/items/vehicle/controls.json #: data/json/vehicleparts/vehicle_parts.json @@ -119657,30 +119949,30 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "internal combustion engine" msgid_plural "internal combustion engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor de combustión interna" +msgstr[1] "motores de combustión interna" +msgstr[2] "motores de combustión interna" #: data/json/items/vehicle/engine.json msgid "base diesel engine" msgid_plural "base diesel engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor diésel" +msgstr[1] "motores diésel" +msgstr[2] "motores diésel" #: data/json/items/vehicle/engine.json msgid "base gasoline engine" msgid_plural "base gasoline engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor a nafta" +msgstr[1] "motores a nafta" +msgstr[2] "motores a nafta" #: data/json/items/vehicle/engine.json msgid "base steam engine" msgid_plural "base steam engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor de vapor" +msgstr[1] "motores de vapor" +msgstr[2] "motores de vapor" #: data/json/items/vehicle/engine.json msgid "1-cylinder engine" @@ -119697,9 +119989,9 @@ msgstr "Un motor de combustión de 4 tiempos, de un solo cilindro." #: data/json/items/vehicle/engine.json msgid "large 1-cylinder engine" msgid_plural "large 1-cylinder engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor grande de 1 cilindro" +msgstr[1] "motores grandes de 1 cilindro" +msgstr[2] "motores grandes de 1 cilindro" #. ~ Description for {'str': 'large 1-cylinder engine'} #: data/json/items/vehicle/engine.json @@ -119812,9 +120104,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "V12 diesel engine" msgid_plural "V12 diesel engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor diésel V12" +msgstr[1] "motores diésel V12" +msgstr[2] "motores diésel V12" #. ~ Description for {'str': 'V12 diesel engine'} #: data/json/items/vehicle/engine.json @@ -119828,9 +120120,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "makeshift steam engine" msgid_plural "makeshift steam engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor de vapor improvisado" +msgstr[1] "motores de vapor improvisado" +msgstr[2] "motores de vapor improvisado" #. ~ Description for {'str': 'makeshift steam engine'} #: data/json/items/vehicle/engine.json @@ -119847,9 +120139,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "small steam engine" msgid_plural "small steam engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor chico de vapor" +msgstr[1] "motores chico de vapor" +msgstr[2] "motores chico de vapor" #. ~ Description for {'str': 'small steam engine'} #: data/json/items/vehicle/engine.json @@ -119866,9 +120158,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "medium steam engine" msgid_plural "medium steam engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor mediano de vapor" +msgstr[1] "motores mediano de vapor" +msgstr[2] "motores mediano de vapor" #. ~ Description for {'str': 'medium steam engine'} #: data/json/items/vehicle/engine.json @@ -119917,9 +120209,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "large engine block" msgid_plural "large engine blocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bloque grande de motor" +msgstr[1] "bloques grandes de motor" +msgstr[2] "bloques grandes de motor" #. ~ Description for {'str': 'large engine block'} #: data/json/items/vehicle/engine.json @@ -119949,9 +120241,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "small engine block" msgid_plural "small engine blocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bloque chico de motor" +msgstr[1] "bloques chicos de motor" +msgstr[2] "bloques chicos de motor" #. ~ Description for {'str': 'small engine block'} #: data/json/items/vehicle/engine.json @@ -119965,9 +120257,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "tiny engine block" msgid_plural "tiny engine blocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bloque pequeño de motor" +msgstr[1] "bloques pequeños de motor" +msgstr[2] "bloques pequeños de motor" #. ~ Description for {'str': 'tiny engine block'} #: data/json/items/vehicle/engine.json @@ -119981,9 +120273,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "1350 hp gas turbine engine" msgid_plural "1350 hp gas turbine engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor de turbina de gas 1350 cv" +msgstr[1] "motores de turbina de gas 1350 cv" +msgstr[2] "motores de turbina de gas 1350 cv" #. ~ Description for {'str': '1350 hp gas turbine engine'} #: data/json/items/vehicle/engine.json @@ -119996,9 +120288,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "1900 hp gas turbine engine" msgid_plural "1900 hp gas turbine engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor de turbina de gas 1900 cv" +msgstr[1] "motores de turbina de gas 1900 cv" +msgstr[2] "motores de turbina de gas 1900 cv" #. ~ Description for {'str': '1900 hp gas turbine engine'} #: data/json/items/vehicle/engine.json @@ -120011,9 +120303,9 @@ msgstr "" #: data/json/items/vehicle/engine.json msgid "6000 hp gas turbine engine" msgid_plural "6000 hp gas turbine engines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "motor de turbina de gas 6000 cv" +msgstr[1] "motores de turbina de gas 6000 cv" +msgstr[2] "motores de turbina de gas 6000 cv" #. ~ Description for {'str': '6000 hp gas turbine engine'} #: data/json/items/vehicle/engine.json @@ -120059,9 +120351,9 @@ msgstr "" #: data/json/vehicleparts/engineering.json msgid "pallet lifter" msgid_plural "pallet lifters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "zorra hidráulica" +msgstr[1] "zorras hidráulicas" +msgstr[2] "zorras hidráulicas" #. ~ Description for {'str': 'pallet lifter'} #: data/json/items/vehicle/engineering.json @@ -120076,9 +120368,9 @@ msgstr "" #: data/json/vehicleparts/engineering.json msgid "rockwheel" msgid_plural "rockwheels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "disco de zanjadora" +msgstr[1] "discos de zanjadora" +msgstr[2] "discos de zanjadora" #. ~ Description for {'str': 'rockwheel'} #: data/json/items/vehicle/engineering.json @@ -120089,9 +120381,9 @@ msgstr "" #: data/json/items/vehicle/engineering.json msgid "airjack" msgid_plural "airjacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gato de aire" +msgstr[1] "gatos de aire" +msgstr[2] "gatos de aire" #. ~ Description for {'str': 'airjack'} #. ~ Description for {'str': 'air jack system'} @@ -120108,9 +120400,9 @@ msgstr "" #: data/json/vehicleparts/engineering.json msgid "motorcycle kickstand" msgid_plural "motorcycle kickstands" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pie para moto" +msgstr[1] "pies para moto" +msgstr[2] "pies para moto" #. ~ Description for {'str': 'motorcycle kickstand'} #: data/json/items/vehicle/engineering.json @@ -120361,9 +120653,9 @@ msgstr "" #: data/json/items/vehicle/lights.json msgid "wide-angle car headlight" msgid_plural "wide-angle car headlights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "luz delantera amplia" +msgstr[1] "luces delanteras amplias" +msgstr[2] "luces delanteras amplias" #. ~ Description for {'str': 'wide-angle car headlight'} #: data/json/items/vehicle/lights.json @@ -120391,9 +120683,9 @@ msgstr "" #: data/json/items/vehicle/lights.json data/json/vehicleparts/lights.json msgid "reinforced wide-angle headlight" msgid_plural "reinforced wide-angle headlights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "luz delantera amplia reforzada" +msgstr[1] "luces delanteras amplias reforzadas" +msgstr[2] "luces delanteras amplias reforzadas" #. ~ Description for {'str': 'reinforced wide-angle headlight'} #: data/json/items/vehicle/lights.json @@ -120498,9 +120790,9 @@ msgstr "Los pedales con los piñones de una bicicleta." #: data/json/vehicleparts/vehicle_parts.json msgid "wind turbine" msgid_plural "wind turbines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "turbina de viento" +msgstr[1] "turbinas de viento" +msgstr[2] "turbinas de viento" #. ~ Description for {'str': 'wind turbine'} #: data/json/items/vehicle/mills.json @@ -120686,9 +120978,9 @@ msgstr "" #: data/json/items/vehicle/noise.json msgid "chime loudspeakers" msgid_plural "chime loudspeakers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carillón" +msgstr[1] "carillones" +msgstr[2] "carillones" #. ~ Description for {'str_sp': 'chime loudspeakers'} #: data/json/items/vehicle/noise.json @@ -120969,9 +121261,9 @@ msgstr "" #: data/json/items/vehicle/rigs.json msgid "vehicle kiln" msgid_plural "vehicle kilns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "fosa de carbonización para vehículo" +msgstr[1] "fosas de carbonización para vehículo" +msgstr[2] "fosas de carbonización para vehículo" #. ~ Description for {'str': 'vehicle kiln'} #: data/json/items/vehicle/rigs.json @@ -121213,9 +121505,9 @@ msgstr "Es una simple mesa de madera." #: data/json/vehicleparts/vehicle_parts.json msgid "turret mount" msgid_plural "turret mounts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "montura para torreta" +msgstr[1] "monturas para torreta" +msgstr[2] "monturas para torreta" #. ~ Description for {'str': 'turret mount'} #: data/json/items/vehicle/turrets.json @@ -125078,9 +125370,9 @@ msgstr "" #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal child" msgid_plural "fungal children" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chico fúngico" +msgstr[1] "chicos fúngicos" +msgstr[2] "chicos fúngicos" #. ~ Description for {'str': 'fungal child', 'str_pl': 'fungal children'} #: data/json/monsters/fungus.json @@ -128146,13 +128438,6 @@ msgstr "" "pálido por su vida subterránea. Se mueve en manada por debajo del suelo y su" " nombre es por su hábito de infestar las cloacas." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "masa" -msgstr[1] "masas" -msgstr[2] "masas" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -128915,13 +129200,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "zombi" -msgstr[1] "zombis" -msgstr[2] "zombis" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -140012,7 +140290,8 @@ msgid "I'll kill you if you don't." msgstr "Te mataré si no lo haces." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "Olvidate." @@ -148264,10 +148543,6 @@ msgstr "monstruo" msgid "demon" msgstr "demonio" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "horror" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "bestia indescifrable" @@ -157773,9 +158048,9 @@ msgstr "" #: data/json/npcs/refugee_center/surface_refugees/NPC_Dana_Nunez.json msgid "Dana's sourdough bread" msgid_plural "Dana's sourdough breads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pan de masa madre de Dana" +msgstr[1] "panes de masa madre de Dana" +msgstr[2] "panes de masa madre de Dana" #. ~ Description for {'str': "Dana's sourdough bread"} #: data/json/npcs/refugee_center/surface_refugees/NPC_Dana_Nunez.json @@ -162562,6 +162837,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -162598,6 +162883,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -164771,9 +165070,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "leaf spring" msgid_plural "leaf springs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "elástico" +msgstr[1] "elásticos" +msgstr[2] "elásticos" #. ~ Description for {'str': 'leaf spring'} #: data/json/obsoletion/items.json @@ -164847,9 +165146,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "rapid blowback" msgid_plural "rapid blowbacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "blowback rápido" +msgstr[1] "blowbacks rápidos" +msgstr[2] "blowbacks rápidos" #: data/json/obsoletion/items.json msgid "" @@ -165114,9 +165413,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "homemade laser pistol" msgid_plural "homemade laser pistols" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pistola láser casera" +msgstr[1] "pistolas láser caseras" +msgstr[2] "pistolas láser caseras" #: data/json/obsoletion/items.json msgid "" @@ -165305,9 +165604,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "spurge" msgid_plural "spurges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "euforbio" +msgstr[1] "euforbios" +msgstr[2] "euforbios" #. ~ Description for {'str': 'spurge'} #: data/json/obsoletion/items.json @@ -165317,9 +165616,9 @@ msgstr "Es un tallo de euforbio con algunos pétalos." #: data/json/obsoletion/items.json msgid "spurge bud" msgid_plural "spurge buds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capullo de euforbio" +msgstr[1] "capullos de euforbio" +msgstr[2] "capullos de euforbio" #. ~ Description for {'str': 'spurge bud'} #: data/json/obsoletion/items.json @@ -165338,9 +165637,9 @@ msgstr "Es un tallo de rudbeckia con algunos pétalos." #: data/json/obsoletion/items.json msgid "black eyed susan bud" msgid_plural "black eyed susan buds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capullo de rudbeckia" +msgstr[1] "capullos de rudbeckia" +msgstr[2] "capullos de rudbeckia" #. ~ Description for {'str': 'black eyed susan bud'} #: data/json/obsoletion/items.json @@ -165359,9 +165658,9 @@ msgstr "Es un tallo de lirio con algunos pétalos." #: data/json/obsoletion/items.json msgid "lily bud" msgid_plural "lily buds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capullo de lirio" +msgstr[1] "capullos de lirio" +msgstr[2] "capullos de lirio" #. ~ Description for {'str': 'lily bud'} #: data/json/obsoletion/items.json @@ -165526,9 +165825,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "40x46mm" msgid_plural "40x46mms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "40x46mm" +msgstr[1] "40x46mm" +msgstr[2] "40x46mm" #. ~ Description for {'str': '40x46mm'} #: data/json/obsoletion/items.json @@ -165558,9 +165857,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "40mm smoke cover" msgid_plural "40mm smoke covers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "40mm fumígena" +msgstr[1] "40mm fumígenas" +msgstr[2] "40mm fumígenas" #. ~ Description for {'str': '40mm smoke cover'} #: data/json/obsoletion/items.json @@ -165570,9 +165869,9 @@ msgstr "Es una granada de 40mm diseñada para crear una cortina de humo." #: data/json/obsoletion/items.json msgid "40mm slug" msgid_plural "40mm slugs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "posta 40mm" +msgstr[1] "postas 40mm" +msgstr[2] "postas 40mm" #. ~ Description for {'str': '40mm slug'} #: data/json/obsoletion/items.json @@ -165587,9 +165886,9 @@ msgstr "" #: data/mods/No_Hope/Items/books.json msgid "chicken walker schematics" msgid_plural "chicken walker schematics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esquema de mecha-gallina" +msgstr[1] "esquemas de mecha-gallina" +msgstr[2] "esquemas de mecha-gallina" #. ~ Description for {'str_sp': 'chicken walker schematics'} #: data/json/obsoletion/items.json data/mods/Aftershock/items/books.json @@ -165692,9 +165991,9 @@ msgstr "" #: data/mods/No_Hope/Items/tools.json msgid "inactive tank drone" msgid_plural "inactive tank drones" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "dron tanque inactivo" +msgstr[1] "drones tanques inactivos" +msgstr[2] "drones tanques inactivos" #. ~ Use action friendly_msg for {'str': 'inactive tank drone'}. #. ~ Use action friendly_msg for inactive tank drone. @@ -165734,9 +166033,9 @@ msgstr "" #: data/mods/No_Hope/Items/generic.json msgid "broken chickenbot" msgid_plural "broken chickenbots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gallinabot rota" +msgstr[1] "gallinabots rotas" +msgstr[2] "gallinabots rotas" #. ~ Use action friendly_msg for {'str': 'broken chickenbot'}. #. ~ Use action friendly_msg for {'str': 'inactive chicken walker'}. @@ -165779,9 +166078,9 @@ msgstr "" #: data/mods/No_Hope/Items/tools.json msgid "inactive tripod" msgid_plural "inactive tripods" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "trípode inactivo" +msgstr[1] "trípodes inactivos" +msgstr[2] "trípodes inactivos" #. ~ Use action friendly_msg for {'str': 'inactive tripod'}. #. ~ Use action friendly_msg for inactive tripod. @@ -165860,9 +166159,9 @@ msgstr "" #: data/mods/No_Hope/Items/generic.json msgid "tripod chassis" msgid_plural "tripod chassis" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chasis de trípode" +msgstr[1] "chasis de trípode" +msgstr[2] "chasis de trípode" #. ~ Description for {'str_sp': 'tripod chassis'} #: data/json/obsoletion/items.json data/mods/Aftershock/items/robotparts.json @@ -165878,9 +166177,9 @@ msgstr "" #: data/mods/No_Hope/Items/generic.json msgid "chicken walker chassis" msgid_plural "chicken walker chassis" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chasis de mecha-gallina" +msgstr[1] "chasis de mecha-gallina" +msgstr[2] "chasis de mecha-gallina" #. ~ Description for {'str_sp': 'chicken walker chassis'} #: data/json/obsoletion/items.json data/mods/Aftershock/items/robotparts.json @@ -165896,9 +166195,9 @@ msgstr "" #: data/mods/No_Hope/Items/generic.json msgid "Beagle chassis" msgid_plural "Beagle chassis" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chasis de Beagle" +msgstr[1] "chasis de Beagle" +msgstr[2] "chasis de Beagle" #. ~ Description for {'str_sp': 'Beagle chassis'} #: data/json/obsoletion/items.json data/mods/Aftershock/items/robotparts.json @@ -165930,9 +166229,9 @@ msgstr "" #: data/mods/No_Hope/Items/generic.json msgid "set of spidery legs" msgid_plural "sets of spidery legs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grupo de piernas arácnidas" +msgstr[1] "grupos de piernas arácnidas" +msgstr[2] "grupos de piernas arácnidas" #. ~ Description for {'str': 'set of spidery legs', 'str_pl': 'sets of spidery #. legs'} @@ -166466,9 +166765,9 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Items/gunmods.json msgid "LW barrel extension" msgid_plural "LW barrel extensions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "extensor de cañón LW" +msgstr[1] "extensores de cañón LW" +msgstr[2] "extensores de cañón LW" #: data/json/obsoletion/items.json data/mods/No_Hope/Items/gunmods.json msgid "" @@ -166481,9 +166780,9 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Items/gunmods.json msgid "LW heavy duty barrel" msgid_plural "LW heavy duty barrels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cañón reforzado LW" +msgstr[1] "cañones reforzados LW" +msgstr[2] "cañones reforzados LW" #: data/json/obsoletion/items.json msgid "" @@ -166612,9 +166911,9 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/Aftershock/items/armor.json msgid "quantum solar backpack (unfolded)" msgid_plural "quantum solar backpacks (unfolded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mochila solar de quántum (desplegada)" +msgstr[1] "mochilas solares de quántum (desplegadas)" +msgstr[2] "mochilas solares de quántum (desplegadas)" #. ~ Description for {'str': 'quantum solar backpack (unfolded)', 'str_pl': #. 'quantum solar backpacks (unfolded)'} @@ -166716,9 +167015,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "238-NK: Practicality Enhancement" msgid_plural "copies of 238-NK: Practicality Enhancement" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "238-NK: Mejoría Práctica" +msgstr[1] "copias de 238-NK: Mejoría Práctica" +msgstr[2] "copias de 238-NK: Mejoría Práctica" #. ~ Description for {'str': '238-NK: Practicality Enhancement', 'str_pl': #. 'copies of 238-NK: Practicality Enhancement'} @@ -166755,9 +167054,9 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "scrap shotcanister" msgid_plural "scrap shotcanisters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bote de metralla con chatarra" +msgstr[1] "botes de metralla con chatarra" +msgstr[2] "botes de metralla con chatarra" #. ~ Description for {'str': 'scrap shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -166771,9 +167070,9 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "pebble shotcanister" msgid_plural "pebble shotcanisters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bote de metralla con piedritas" +msgstr[1] "botes de metralla con piedritas" +msgstr[2] "botes de metralla con piedritas" #. ~ Description for {'str': 'pebble shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -166789,9 +167088,9 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "flechette shotcanister" msgid_plural "flechette shotcanisters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bote de metralla con dardos perforantes" +msgstr[1] "botes de metralla con dardos perforantes" +msgstr[2] "botes de metralla con dardos perforantes" #. ~ Description for {'str': 'flechette shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -166806,9 +167105,9 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "bearing shotcanister" msgid_plural "bearing shotcanisters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bote de metralla con rulemanes" +msgstr[1] "botes de metralla con rulemanes" +msgstr[2] "botes de metralla con rulemanes" #. ~ Description for {'str': 'bearing shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -167511,9 +167810,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "score card" msgid_plural "score cards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tarjeta de resultado" +msgstr[1] "tarjetas de resultado" +msgstr[2] "tarjetas de resultado" #. ~ Description for {'str': 'score card'} #: data/json/obsoletion/items.json @@ -167537,9 +167836,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "empty ballistic vest" msgid_plural "empty ballistic vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco de balística vacío" +msgstr[1] "chalecos de balística vacíos" +msgstr[2] "chalecos de balística vacíos" #. ~ Description for {'str': 'empty ballistic vest'} #: data/json/obsoletion/items.json @@ -167554,9 +167853,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "ESAPI ballistic vest" msgid_plural "ESAPI ballistic vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco de balística ESAPI" +msgstr[1] "chalecos de balística ESAPI" +msgstr[2] "chalecos de balística ESAPI" #. ~ Description for {'str': 'ESAPI ballistic vest'} #: data/json/obsoletion/items.json @@ -167691,23 +167990,23 @@ msgstr "" #: data/json/obsoletion/items.json msgid "broken M249 autonomous CROWS II" msgid_plural "broken M249 autonomous CROWS II turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta M249 autónoma CROWS II rota" +msgstr[1] "torretas M249 autónomas CROWS II rotas" +msgstr[2] "torretas M249 autónomas CROWS II rotas" #: data/json/obsoletion/items.json msgid "broken M240 autonomous CROWS II" msgid_plural "broken M240 autonomous CROWS II turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta M240 autónoma CROWS II rota" +msgstr[1] "torretas M240 autónomas CROWS II rotas" +msgstr[2] "torretas M240 autónomas CROWS II rotas" #: data/json/obsoletion/items.json msgid "broken M2 autonomous CROWS II" msgid_plural "broken M2 autonomous CROWS II turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta M2 autónoma CROWS II rota" +msgstr[1] "torretas M2 autónomas CROWS II rotas" +msgstr[2] "torretas M2 autónomas CROWS II rotas" #: data/json/obsoletion/items.json #: data/mods/Generic_Guns/robots/inactive_bots.json @@ -167732,9 +168031,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".22 CB" msgid_plural ".22 CBs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".22 CB" +msgstr[1] ".22 CB" +msgstr[2] ".22 CB" #. ~ Description for {'str': '.22 CB'} #: data/json/obsoletion/items.json @@ -167837,9 +168136,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "rubber sole" msgid_plural "rubber soles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suela de goma" +msgstr[1] "suelas de goma" +msgstr[2] "suelas de goma" #. ~ Description for {'str': 'rubber sole'} #: data/json/obsoletion/items.json @@ -167851,16 +168150,16 @@ msgstr "Es una suela hecha de goma, comúnmente usado en botas." #: data/json/obsoletion/items.json msgid "tÖttchen" msgid_plural "tÖttchens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tÖttchen" +msgstr[1] "tÖttchen" +msgstr[2] "tÖttchen" #: data/json/obsoletion/items.json msgid "glycerol" msgid_plural "glycerol" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "glicerol" +msgstr[1] "glicerol" +msgstr[2] "glicerol" #. ~ Description for {'str_sp': 'glycerol'} #: data/json/obsoletion/items.json @@ -167889,9 +168188,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "acrylamide" msgid_plural "acrylamide" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "acrilamida" +msgstr[1] "acrilamida" +msgstr[2] "acrilamida" #. ~ Description for {'str_sp': 'acrylamide'} #: data/json/obsoletion/items.json @@ -167905,9 +168204,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "butchery refuse" msgid_plural "butchery refuse" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "desechos" +msgstr[1] "desechos" +msgstr[2] "desechos" #. ~ Description for {'str_sp': 'butchery refuse'} #: data/json/obsoletion/items.json @@ -167925,9 +168224,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "microwave generator" msgid_plural "microwave generators" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "generador de microondas" +msgstr[1] "generadores de microondas" +msgstr[2] "generadores de microondas" #. ~ Description for {'str': 'microwave generator'} #: data/json/obsoletion/items.json @@ -168080,9 +168379,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "curdling milk" msgid_plural "curdling milks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche cuajando" +msgstr[1] "leches cuajando" +msgstr[2] "leches cuajando" #. ~ Description for curdling milk #: data/json/obsoletion/items.json @@ -168094,9 +168393,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "curdled milk" msgid_plural "curdled milks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "leche cuajada" +msgstr[1] "leche cuajada" +msgstr[2] "leche cuajada" #. ~ Description for curdled milk #: data/json/obsoletion/items.json @@ -168108,9 +168407,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "buttermilk" msgid_plural "buttermilk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de manteca" +msgstr[1] "suero de manteca" +msgstr[2] "suero de manteca" #. ~ Description for {'str_sp': 'buttermilk'} #: data/json/obsoletion/items.json @@ -168124,9 +168423,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "heavy cream" msgid_plural "heavy cream" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "crema de leche" +msgstr[1] "crema de leche" +msgstr[2] "crema de leche" #. ~ Description for {'str_sp': 'heavy cream'} #: data/json/obsoletion/items.json @@ -168178,9 +168477,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "5x50mm flechette, reloaded" msgid_plural "5x50mm flechette, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5x50mm dardos perforantes, recargada" +msgstr[1] "5x50mm dardos perforantes, recargadas" +msgstr[2] "5x50mm dardos perforantes, recargadas" #. ~ Description for {'str': '5x50mm flechette, reloaded'} #: data/json/obsoletion/items.json @@ -168196,37 +168495,37 @@ msgstr "" #: data/json/obsoletion/items.json msgid "9x19mm JHP, reloaded" msgid_plural "9x19mm JHP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm JHP, recargada" +msgstr[1] "9x19mm JHP, recargadas" +msgstr[2] "9x19mm JHP, recargadas" #: data/json/obsoletion/items.json msgid "9x19mm FMJ, reloaded" msgid_plural "9x19mm FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm FMJ, recargada" +msgstr[1] "9x19mm FMJ, recargadas" +msgstr[2] "9x19mm FMJ, recargadas" #: data/json/obsoletion/items.json msgid "9x19mm +P, reloaded" msgid_plural "9x19mm +P, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm +P, recargada" +msgstr[1] "9x19mm +P, recargadas" +msgstr[2] "9x19mm +P, recargadas" #: data/json/obsoletion/items.json msgid "9x19mm +P+, reloaded" msgid_plural "9x19mm +P+, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x19mm +P+, recargada" +msgstr[1] "9x19mm +P+, recargadas" +msgstr[2] "9x19mm +P+, recargadas" #: data/json/obsoletion/items.json msgid "9x18mm, reloaded" msgid_plural "9x18mm, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm, recargada" +msgstr[1] "9x18mm, recargadas" +msgstr[2] "9x18mm, recargadas" #. ~ Description for {'str': '9x18mm, reloaded'} #: data/json/obsoletion/items.json @@ -168242,9 +168541,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "9x18mm +P+, reloaded" msgid_plural "9x18mm +P+, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm +P+, recargada" +msgstr[1] "9x18mm +P+, recargadas" +msgstr[2] "9x18mm +P+, recargadas" #. ~ Description for {'str': '9x18mm +P+, reloaded'} #: data/json/obsoletion/items.json @@ -168260,9 +168559,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "9x18mm FMJ, reloaded" msgid_plural "9x18mm FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "9x18mm FMJ, recargada" +msgstr[1] "9x18mm FMJ, recargadas" +msgstr[2] "9x18mm FMJ, recargadas" #. ~ Description for {'str': '9x18mm FMJ, reloaded'} #: data/json/obsoletion/items.json @@ -168279,16 +168578,16 @@ msgstr "" #: data/json/obsoletion/items.json msgid "10mm Auto FMJ, reloaded" msgid_plural "10mm Auto FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "10mm Auto FMJ, recargada" +msgstr[1] "10mm Auto FMJ, recargada" +msgstr[2] "10mm Auto FMJ, recargada" #: data/json/obsoletion/items.json msgid ".22 LR, reloaded" msgid_plural ".22 LR, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".22 LR, recargada" +msgstr[1] ".22 LR, recargadas" +msgstr[2] ".22 LR, recargadas" #: data/json/obsoletion/items.json msgid ".22 CPHP, reloaded" @@ -168300,107 +168599,107 @@ msgstr[2] "" #: data/json/obsoletion/items.json msgid ".32 ACP, reloaded" msgid_plural ".32 ACP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".32 ACP, recargada" +msgstr[1] ".32 ACP, recargadas" +msgstr[2] ".32 ACP, recargadas" #: data/json/obsoletion/items.json msgid ".38 FMJ, reloaded" msgid_plural ".38 FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 FMJ, recargada" +msgstr[1] ".38 FMJ, recargadas" +msgstr[2] ".38 FMJ, recargadas" #: data/json/obsoletion/items.json msgid ".38 Special, reloaded" msgid_plural ".38 Special, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 Special, recargada" +msgstr[1] ".38 Special, recargadas" +msgstr[2] ".38 Special, recargadas" #: data/json/obsoletion/items.json msgid ".38 Super FMJ, reloaded" msgid_plural ".38 Super FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 Super FMJ, recargada" +msgstr[1] ".38 Super FMJ, recargadas" +msgstr[2] ".38 Super FMJ, recargadas" #: data/json/obsoletion/items.json msgid ".38 Super, reloaded" msgid_plural ".38 Super, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".38 Super, recargada" +msgstr[1] ".38 Super, recargadas" +msgstr[2] ".38 Super, recargadas" #: data/json/obsoletion/items.json msgid ".40 S&W FMJ, reloaded" msgid_plural ".40 S&W FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".40 S&W FMJ, recargada" +msgstr[1] ".40 S&W FMJ, recargadas" +msgstr[2] ".40 S&W FMJ, recargadas" #: data/json/obsoletion/items.json msgid ".40 S&W JHP, reloaded" msgid_plural ".40 S&W JHP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".40 S&W JHP, recargada" +msgstr[1] ".40 S&W JHP, recargadas" +msgstr[2] ".40 S&W JHP, recargadas" #: data/json/obsoletion/items.json msgid ".44 Magnum FMJ, reloaded" msgid_plural ".44 Magnum FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".44 Magnum FMJ, recargada" +msgstr[1] ".44 Magnum FMJ, recargadas" +msgstr[2] ".44 Magnum FMJ, recargadas" #: data/json/obsoletion/items.json msgid ".44 Magnum, reloaded" msgid_plural ".44 Magnum, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".44 Magnum, recargada" +msgstr[1] ".44 Magnum, recargadas" +msgstr[2] ".44 Magnum, recargadas" #: data/json/obsoletion/items.json msgid ".45 FMJ, reloaded" msgid_plural ".45 FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 FMJ, recargada" +msgstr[1] ".45 FMJ, recargadas" +msgstr[2] ".45 FMJ, recargadas" #: data/json/obsoletion/items.json msgid ".45 ACP JHP, reloaded" msgid_plural ".45 ACP JHP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 ACP JHP, recargada" +msgstr[1] ".45 ACP JHP, recargadas" +msgstr[2] ".45 ACP JHP, recargadas" #: data/json/obsoletion/items.json msgid ".45 ACP +P, reloaded" msgid_plural ".45 ACP +P, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 ACP +P, recargada" +msgstr[1] ".45 ACP +P, recargadas" +msgstr[2] ".45 ACP +P, recargadas" #: data/json/obsoletion/items.json msgid ".45 Colt JHP, reloaded" msgid_plural ".45 Colt JHP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45 Colt JHP, recargada" +msgstr[1] ".45 Colt JHP, recargadas" +msgstr[2] ".45 Colt JHP, recargadas" #: data/json/obsoletion/items.json msgid "4.6x30mm, reloaded" msgid_plural "4.6x30mm, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "4.6x30mm, recargada" +msgstr[1] "4.6x30mm, recargadas" +msgstr[2] "4.6x30mm, recargadas" #: data/json/obsoletion/items.json msgid ".50 BMG tracer, reloaded" msgid_plural ".50 BMG tracer, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG trazadora, recargada" +msgstr[1] ".50 BMG trazadoras, recargadas" +msgstr[2] ".50 BMG trazadoras, recargadas" #. ~ Description for {'str': '.50 BMG tracer, reloaded'} #: data/json/obsoletion/items.json @@ -168416,9 +168715,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".50 BMG Match, reloaded" msgid_plural ".50 BMG Match, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG Match, recargada" +msgstr[1] ".50 BMG Match, recargadas" +msgstr[2] ".50 BMG Match, recargadas" #. ~ Description for {'str': '.50 BMG Match, reloaded'} #: data/json/obsoletion/items.json @@ -168438,9 +168737,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".50 BMG AP, reloaded" msgid_plural ".50 BMG AP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".50 BMG AP, recargada" +msgstr[1] ".50 BMG AP, recargadas" +msgstr[2] ".50 BMG AP, recargadas" #. ~ Description for {'str': '.50 BMG AP, reloaded'} #: data/json/obsoletion/items.json @@ -168455,9 +168754,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "5.7x28mm, reloaded" msgid_plural "5.7x28mm, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5.7x28mm, recargada" +msgstr[1] "5.7x28mm, recargadas" +msgstr[2] "5.7x28mm, recargadas" #: data/json/obsoletion/items.json msgid "5.56x45mm '.223 Remington', reloaded" @@ -168483,16 +168782,16 @@ msgstr[2] "" #: data/json/obsoletion/items.json msgid ".270 Winchester JSP, reloaded" msgid_plural ".270 Winchester JSP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".270 Winchester JSP, recargada" +msgstr[1] ".270 Winchester JSP, recargadas" +msgstr[2] ".270 Winchester JSP, recargadas" #: data/json/obsoletion/items.json msgid ".300 Winchester Magnum, reloaded" msgid_plural ".300 Winchester Magnum, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".300 Winchester Magnum, recargada" +msgstr[1] ".300 Winchester Magnum, recargadas" +msgstr[2] ".300 Winchester Magnum, recargadas" #. ~ Description for {'str': '.300 Winchester Magnum, reloaded'} #: data/json/obsoletion/items.json @@ -168508,9 +168807,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".300 AAC Blackout, reloaded" msgid_plural ".300 AAC Blackout, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".300 AAC Blackout, recargada" +msgstr[1] ".300 AAC Blackout, recargadas" +msgstr[2] ".300 AAC Blackout, recargadas" #. ~ Description for {'str': '.300 AAC Blackout, reloaded'} #: data/json/obsoletion/items.json @@ -168537,86 +168836,86 @@ msgstr[2] "" #: data/json/obsoletion/items.json msgid "7.62x51mm, reloaded" msgid_plural "7.62x51mm, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x51mm, recargada" +msgstr[1] "7.62x51mm, recargadas" +msgstr[2] "7.62x51mm, recargadas" #: data/json/obsoletion/items.json msgid "7.62x51mm incendiary, reloaded" msgid_plural "7.62x51mm incendiary, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x51mm incendiaria, recargada" +msgstr[1] "7.62x51mm incendiarias, recargadas" +msgstr[2] "7.62x51mm incendiarias, recargadas" #: data/json/obsoletion/items.json msgid ".357 Magnum FMJ, reloaded" msgid_plural ".357 Magnum FMJ, reloaded" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 Magnum FMJ, recargada" +msgstr[1] ".357 Magnum FMJ, recargada" +msgstr[2] ".357 Magnum FMJ, recargada" #: data/json/obsoletion/items.json msgid ".357 Magnum JHP, reloaded" msgid_plural ".357 Magnum JHP, reloaded" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 Magnum JHP, recargada" +msgstr[1] ".357 Magnum JHP, recargada" +msgstr[2] ".357 Magnum JHP, recargada" #: data/json/obsoletion/items.json msgid ".357 SIG FMJ, reloaded" msgid_plural ".357 SIG FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 SIG FMJ, recargada" +msgstr[1] ".357 SIG FMJ, recargadas" +msgstr[2] ".357 SIG FMJ, recargadas" #: data/json/obsoletion/items.json msgid ".357 SIG JHP, reloaded" msgid_plural ".357 SIG JHP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".357 SIG JHP, recargada" +msgstr[1] ".357 SIG JHP, recargadas" +msgstr[2] ".357 SIG JHP, recargadas" #: data/json/obsoletion/items.json msgid ".380 ACP FMJ, reloaded" msgid_plural ".380 ACP FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP FMJ, recargada" +msgstr[1] ".380 ACP FMJ, recargadas" +msgstr[2] ".380 ACP FMJ, recargadas" #: data/json/obsoletion/items.json msgid ".380 ACP JHP, reloaded" msgid_plural ".380 ACP JHP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP JHP, recargada" +msgstr[1] ".380 ACP JHP, recargadas" +msgstr[2] ".380 ACP JHP, recargadas" #: data/json/obsoletion/items.json msgid ".380 ACP +P, reloaded" msgid_plural ".380 ACP +P, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".380 ACP +P, recargada" +msgstr[1] ".380 ACP +P, recargadas" +msgstr[2] ".380 ACP +P, recargadas" #: data/json/obsoletion/items.json msgid ".410 000 shot, reloaded" msgid_plural ".410 000 shot, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho .410 000, recargado" +msgstr[1] "cartuchos .410 000, recargados" +msgstr[2] "cartuchos .410 000, recargados" #: data/json/obsoletion/items.json msgid ".454 Casull, reloaded" msgid_plural ".454 Casull, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".454 Casull, recargada" +msgstr[1] ".454 Casull, recargadas" +msgstr[2] ".454 Casull, recargadas" #: data/json/obsoletion/items.json msgid ".460 Rowland FMJ, reloaded" msgid_plural ".460 Rowland FMJ, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".460 Rowland FMJ, recargada" +msgstr[1] ".460 Rowland FMJ, recargadas" +msgstr[2] ".460 Rowland FMJ, recargadas" #. ~ Description for {'str': '.460 Rowland FMJ, reloaded'} #: data/json/obsoletion/items.json @@ -168630,23 +168929,23 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".460 Rowland, reloaded" msgid_plural ".460 Rowland, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".460 Rowland, recargada" +msgstr[1] ".460 Rowland, recargadas" +msgstr[2] ".460 Rowland, recargadas" #: data/json/obsoletion/items.json msgid ".500 S&W Magnum, reloaded" msgid_plural ".500 S&W Magnum, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".500 S&W Magnum, recargada" +msgstr[1] ".500 S&W Magnum, recargadas" +msgstr[2] ".500 S&W Magnum, recargadas" #: data/json/obsoletion/items.json msgid "5.45x39mm, reloaded" msgid_plural "5.45x39mm, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5.45x39mm, recargada" +msgstr[1] "5.45x39mm, recargadas" +msgstr[2] "5.45x39mm, recargadas" #. ~ Description for {'str': '5.45x39mm, reloaded'} #: data/json/obsoletion/items.json @@ -168662,9 +168961,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "5.45x39mm AP, reloaded" msgid_plural "5.45x39mm AP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "5.45x39mm AP, recargada" +msgstr[1] "5.45x39mm AP, recargadas" +msgstr[2] "5.45x39mm AP, recargadas" #. ~ Description for {'str': '5.45x39mm AP, reloaded'} #: data/json/obsoletion/items.json @@ -168678,16 +168977,16 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".700 NX, reloaded" msgid_plural ".700 NX, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".700 NX, recargada" +msgstr[1] ".700 NX, recargadas" +msgstr[2] ".700 NX, recargadas" #: data/json/obsoletion/items.json msgid "7.62x39mm M43, reloaded" msgid_plural "7.62x39mm M43, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x39mm M43, recargada" +msgstr[1] "7.62x39mm M43, recargadas" +msgstr[2] "7.62x39mm M43, recargadas" #. ~ Description for {'str': '7.62x39mm M43, reloaded'} #: data/json/obsoletion/items.json @@ -168705,51 +169004,51 @@ msgstr "" #: data/json/obsoletion/items.json msgid "7.62x39mm M67, reloaded" msgid_plural "7.62x39mm M67, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x39mm M67, recargada" +msgstr[1] "7.62x39mm M67, recargadas" +msgstr[2] "7.62x39mm M67, recargadas" #: data/json/obsoletion/items.json msgid "7.62x54mmR, reloaded" msgid_plural "7.62x54mmR, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x54mmR, recargada" +msgstr[1] "7.62x54mmR, recargadas" +msgstr[2] "7.62x54mmR, recargadas" #: data/json/obsoletion/items.json msgid "7.62x25mm, reloaded" msgid_plural "7.62x25mm, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "7.62x25mm, recargada" +msgstr[1] "7.62x25mm, recargadas" +msgstr[2] "7.62x25mm, recargadas" #: data/json/obsoletion/items.json msgid ".30-06 Springfield, reloaded" msgid_plural ".30-06 Springfield, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 Springfield, recargada" +msgstr[1] ".30-06 Springfield, recargadas" +msgstr[2] ".30-06 Springfield, recargadas" #: data/json/obsoletion/items.json msgid ".30-06 incendiary, reloaded" msgid_plural ".30-06 incendiary, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 incendiaria, recargada" +msgstr[1] ".30-06 incendiarias, recargadas" +msgstr[2] ".30-06 incendiarias, recargadas" #: data/json/obsoletion/items.json msgid ".30-06 M2 AP, reloaded" msgid_plural ".30-06 M2 AP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".30-06 M2 AP, recargada" +msgstr[1] ".30-06 M2 AP, recargadas" +msgstr[2] ".30-06 M2 AP, recargadas" #: data/json/obsoletion/items.json msgid ".45-70 SP, reloaded" msgid_plural ".45-70 SP, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45-70 SP, recargada" +msgstr[1] ".45-70 SP, recargadas" +msgstr[2] ".45-70 SP, recargadas" #. ~ Description for {'str': '.45-70 SP, reloaded'} #: data/json/obsoletion/items.json @@ -168765,9 +169064,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".45-70 +P penetrator, reloaded" msgid_plural ".45-70 +P penetrator, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45-70 +P perforante, recargada" +msgstr[1] ".45-70 +P perforante, recargadas" +msgstr[2] ".45-70 +P perforante, recargadas" #. ~ Description for {'str': '.45-70 +P penetrator, reloaded'} #: data/json/obsoletion/items.json @@ -168785,9 +169084,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".45-70 LFN cowboy, reloaded" msgid_plural ".45-70 LFN cowboy, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] ".45-70 LFN cowboy, recargada" +msgstr[1] ".45-70 LFN cowboy, recargadas" +msgstr[2] ".45-70 LFN cowboy, recargadas" #. ~ Description for {'str': '.45-70 LFN cowboy, reloaded'} #: data/json/obsoletion/items.json @@ -168804,37 +169103,37 @@ msgstr "" #: data/json/obsoletion/items.json msgid "birdshot, reloaded" msgid_plural "birdshot, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perdigones pequeños, recargado" +msgstr[1] "perdigones pequeños, recargados" +msgstr[2] "perdigones pequeños, recargados" #: data/json/obsoletion/items.json msgid "dragon's breath shell, reloaded" msgid_plural "dragon's breath shell, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho aliento de dragón, recargado" +msgstr[1] "cartuchos aliento de dragón, recargados" +msgstr[2] "cartuchos aliento de dragón, recargados" #: data/json/obsoletion/items.json msgid "00 shot, reloaded" msgid_plural "00 shot, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho 00, recargado" +msgstr[1] "cartuchos 00, recargados" +msgstr[2] "cartuchos 00, recargados" #: data/json/obsoletion/items.json msgid "flechette shell, reloaded" msgid_plural "flechette shell, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de dardos perforantes, recargado" +msgstr[1] "cartuchos de dardos perforantes, recargados" +msgstr[2] "cartuchos de dardos perforantes, recargados" #: data/json/obsoletion/items.json msgid "shotgun slug, reloaded" msgid_plural "shotgun slug, reloadeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "posta de escopeta, recargada" +msgstr[1] "postas de escopeta, recargadas" +msgstr[2] "postas de escopeta, recargadas" #: data/json/obsoletion/items.json msgid "flu shot" @@ -169023,9 +169322,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "Lycra scraps" msgid_plural "Lycra scraps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedazos de licra" +msgstr[1] "pedazos de licra" +msgstr[2] "pedazos de licra" #. ~ Description for {'str_sp': 'Lycra scraps'} #: data/json/obsoletion/items.json @@ -169039,9 +169338,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "Lycra sheet" msgid_plural "Lycra sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tela de licra" +msgstr[1] "telas de licra" +msgstr[2] "telas de licra" #. ~ Description for {'str': 'Lycra sheet'} #: data/json/obsoletion/items.json @@ -169055,9 +169354,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "patchwork Lycra clothing parts" msgid_plural "patchwork Lycra clothing parts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "retazos de ropa de licra" +msgstr[1] "retazos de ropa de licra" +msgstr[2] "retazos de ropa de licra" #. ~ Description for {'str_sp': 'patchwork Lycra clothing parts'} #: data/json/obsoletion/items.json @@ -169085,9 +169384,9 @@ msgstr "" #: data/json/obsoletion/items.json msgid "set of spectrometry cuvettes" msgid_plural "sets of spectrometry cuvettes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "equipo de cuvettes de espectrometría" +msgstr[1] "equipos de cuvettes de espectrometría" +msgstr[2] "equipos de cuvettes de espectrometría" #. ~ Description for {'str': 'set of spectrometry cuvettes', 'str_pl': 'sets #. of spectrometry cuvettes'} @@ -191141,9 +191440,9 @@ msgstr "Centro de Despacho de Robots" #: data/mods/Aftershock/items/ammo_type.json msgid "acidic bore" msgid_plural "acidic bores" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "ácido bórico" +msgstr[1] "ácido bórico" +msgstr[2] "ácido bórico" #. ~ Description for {'str': 'acidic bore'} #: data/mods/Aftershock/items/ammo.json @@ -191172,9 +191471,9 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "bag of holding" msgid_plural "bags of holding" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de almacenamiento" +msgstr[1] "bolsas de almacenamiento" +msgstr[2] "bolsas de almacenamiento" #. ~ Description for {'str': 'bag of holding', 'str_pl': 'bags of holding'} #: data/mods/Aftershock/items/armor.json @@ -191229,9 +191528,9 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "sentinel-lx cloak" msgid_plural "sentinel-lx cloaks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "capa sentinel-lx" +msgstr[1] "capas sentinel-lx" +msgstr[2] "capas sentinel-lx" #. ~ Description for {'str': 'sentinel-lx cloak'} #: data/mods/Aftershock/items/armor.json @@ -191302,9 +191601,9 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "Uplifted SWAT armor" msgid_plural "Uplifted SWAT armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura SWAT ciclópea" +msgstr[1] "armaduras SWAT ciclópeas" +msgstr[2] "armaduras SWAT ciclópeas" #. ~ Description for {'str': 'Uplifted SWAT armor'} #: data/mods/Aftershock/items/armor.json @@ -191320,9 +191619,9 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "empty XL ballistic vest" msgid_plural "empty XL ballistic vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco XL de balística vacío" +msgstr[1] "chalecos XL de balística vacíos" +msgstr[2] "chalecos XL de balística vacíos" #. ~ Description for {'str': 'empty XL ballistic vest'} #: data/mods/Aftershock/items/armor.json @@ -191337,9 +191636,9 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "XL ESAPI ballistic vest" msgid_plural "XL ESAPI ballistic vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco XL de balística ESAPI" +msgstr[1] "chalecos XL de balística ESAPI" +msgstr[2] "chalecos XL de balística ESAPI" #. ~ Description for {'str': 'XL ESAPI ballistic vest'} #: data/mods/Aftershock/items/armor.json @@ -191349,9 +191648,9 @@ msgstr "Es armadura balística de gran tamaño con placas ESAPI de cerámica." #: data/mods/Aftershock/items/armor.json msgid "pair of XL combat boots" msgid_plural "pair of XL combat boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas XL de combate" +msgstr[1] "pares de botas XL de combate" +msgstr[2] "pares de botas XL de combate" #. ~ Description for {'str_sp': 'pair of XL combat boots'} #: data/mods/Aftershock/items/armor.json @@ -191361,9 +191660,9 @@ msgstr "Son unas botas tácticas grandes de combate reforzadas. Muy duraderas." #: data/mods/Aftershock/items/armor.json msgid "pair of XL tactical gloves" msgid_plural "pair of XL tactical gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes XL tácticos" +msgstr[1] "pares de guantes XL tácticos" +msgstr[2] "pares de guantes XL tácticos" #. ~ Description for {'str_sp': 'pair of XL tactical gloves'} #: data/mods/Aftershock/items/armor.json @@ -191377,9 +191676,9 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "pair of Killophant gloves" msgid_plural "pair of Killophant gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes Asesifante" +msgstr[1] "pares de guantes Asesifante" +msgstr[2] "pares de guantes Asesifante" #. ~ Description for {'str_sp': 'pair of Killophant gloves'} #: data/mods/Aftershock/items/armor.json @@ -191579,9 +191878,9 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "USMC M1014 technical manual" msgid_plural "USMC M1014 technical manuals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "manual técnico de USMC M1014" +msgstr[1] "manuales técnicos de USMC M1014" +msgstr[2] "manuales técnicos de USMC M1014" #. ~ Description for {'str': 'USMC M1014 technical manual'} #: data/mods/Aftershock/items/books.json @@ -191599,9 +191898,9 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Black Powder to Berettas" msgid_plural "copies of Black Powder to Berettas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "copia de Pólvora Negra para Berettas" +msgstr[1] "copias de Pólvora Negra para Berettas" +msgstr[2] "copias de Pólvora Negra para Berettas" #. ~ Description for {'str': 'Black Powder to Berettas', 'str_pl': 'copies of #. Black Powder to Berettas'} @@ -191642,9 +191941,9 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Jane's Flamethrowers and Firestarters" msgid_plural "copies of Jane's Flamethrowers and Firestarters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "copia de Lanzallamas y Enciendefuegos de Jane" +msgstr[1] "copias de Lanzallamas y Enciendefuegos de Jane" +msgstr[2] "copias de Lanzallamas y Enciendefuegos de Jane" #. ~ Description for {'str': "Jane's Flamethrowers and Firestarters", #. 'str_pl': "copies of Jane's Flamethrowers and Firestarters"} @@ -191663,9 +191962,9 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Nuclear Physics Made Easy" msgid_plural "copies of Nuclear Physics Made Easy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Física Nuclear para Principiantes" +msgstr[1] "copias de Física Nuclear para Principiantes" +msgstr[2] "copias de Física Nuclear para Principiantes" #. ~ Description for {'str': 'Nuclear Physics Made Easy', 'str_pl': 'copies of #. Nuclear Physics Made Easy'} @@ -191695,9 +191994,9 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Dr Moreau and You" msgid_plural "copies of Dr Moreau and You" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Dr. Moreau y vos" +msgstr[1] "copias de Dr. Moreau y vos" +msgstr[2] "copias de Dr. Moreau y vos" #. ~ Description for {'str': 'Dr Moreau and You', 'str_pl': 'copies of Dr #. Moreau and You'} @@ -191716,9 +192015,9 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Millyficent's Diary" msgid_plural "copies of Millyficent's Diary" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Diario de Millyficent" +msgstr[1] "copias de Diario de Millyficent" +msgstr[2] "copias de Diario de Millyficent" #. ~ Description for {'str': "Millyficent's Diary", 'str_pl': "copies of #. Millyficent's Diary"} @@ -191822,9 +192121,9 @@ msgstr "" #: data/mods/Aftershock/items/cbms.json msgid "Wind Turbine CBM" msgid_plural "Wind Turbine CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Turbina de Viento" +msgstr[1] "MCB Turbina de Viento" +msgstr[2] "MCB Turbina de Viento" #. ~ Description for {'str': 'Wind Turbine CBM'} #. ~ Description for {'str': 'Wind Turbines'} @@ -191874,9 +192173,9 @@ msgstr "" #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "nutriment" msgid_plural "nutriments" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "nutriente" +msgstr[1] "nutrientes" +msgstr[2] "nutrientes" #. ~ Description for nutriment #: data/mods/Aftershock/items/comestibles.json @@ -191895,9 +192194,9 @@ msgstr "" #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "nutriment water" msgid_plural "nutriment waters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "agua nutriente" +msgstr[1] "aguas nutrientes" +msgstr[2] "aguas nutrientes" #. ~ Description for nutriment water #: data/mods/Aftershock/items/comestibles.json @@ -191912,9 +192211,9 @@ msgstr "" #: data/mods/Aftershock/items/comestibles.json msgid "sundew" msgid_plural "sundews" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rocío de sol" +msgstr[1] "rocíos de sol" +msgstr[2] "rocíos de sol" #. ~ Description for sundew #: data/mods/Aftershock/items/comestibles.json @@ -191931,9 +192230,9 @@ msgstr "" #: data/mods/Aftershock/items/comestibles/comestibles.json msgid "sungel" msgid_plural "sungels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "gel del sol" +msgstr[1] "geles del sol" +msgstr[2] "geles del sol" #. ~ Use action activation_message for sungel. #: data/mods/Aftershock/items/comestibles.json @@ -191960,9 +192259,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "sunesthesia" msgid_plural "sunesthesias" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "solnestesia" +msgstr[1] "solnestesias" +msgstr[2] "solnestesias" #. ~ Use action activation_message for sunesthesia. #: data/mods/Aftershock/items/comestibles.json @@ -192017,9 +192316,9 @@ msgstr "" #: data/mods/Modular_Turrets/corpses.json msgid "broken utility robot" msgid_plural "broken utility robots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "utilitaribot roto" +msgstr[1] "utilitaribots rotos" +msgstr[2] "utilitaribots rotos" #. ~ Description for broken utility robot #: data/mods/Aftershock/items/corpses.json @@ -192055,9 +192354,9 @@ msgstr[2] "" #: data/mods/Aftershock/items/corpses.json msgid "broken butler-bot" msgid_plural "broken butler-bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mayordobot roto" +msgstr[1] "mayordobots rotos" +msgstr[2] "mayordobots rotos" #. ~ Description for broken butler-bot #: data/mods/Aftershock/items/corpses.json @@ -192103,9 +192402,9 @@ msgstr "" #: data/mods/Aftershock/items/corpses.json msgid "broken rat snatcher" msgid_plural "broken rat snatchers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cazaratas roto" +msgstr[1] "cazaratas rotos" +msgstr[2] "cazaratas rotos" #. ~ Description for broken rat snatcher #: data/mods/Aftershock/items/corpses.json @@ -192119,9 +192418,9 @@ msgstr "" #: data/mods/Aftershock/items/corpses.json msgid "broken grab-bot" msgid_plural "broken grab-bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "agarrabot roto" +msgstr[1] "agarrabots rotos" +msgstr[2] "agarrabots rotos" #. ~ Description for broken grab-bot #: data/mods/Aftershock/items/corpses.json @@ -192135,9 +192434,9 @@ msgstr "" #: data/mods/Aftershock/items/corpses.json msgid "broken pest hunter" msgid_plural "broken pest hunters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cazapestes roto" +msgstr[1] "cazapestes rotos" +msgstr[2] "cazapestes rotos" #. ~ Description for broken pest hunter #: data/mods/Aftershock/items/corpses.json @@ -192207,9 +192506,9 @@ msgstr "" #: data/mods/Aftershock/items/corpses.json msgid "broken floating heater" msgid_plural "broken floating heaters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "calentador flotante roto" +msgstr[1] "calentadores flotantes rotos" +msgstr[2] "calentadores flotantes rotos" #. ~ Description for broken floating heater #: data/mods/Aftershock/items/corpses.json @@ -192242,9 +192541,9 @@ msgstr "" #: data/mods/Aftershock/items/corpses.json msgid "broken disarmed advanced bot" msgid_plural "broken disarmed advanced bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "robot avanzado desarmado y roto" +msgstr[1] "robots avanzados desarmados y rotos" +msgstr[2] "robots avanzados desarmados y rotos" #. ~ Description for broken disarmed advanced bot #: data/mods/Aftershock/items/corpses.json @@ -192292,16 +192591,16 @@ msgstr[2] "robots militares desarmados y rotos" #: data/mods/Modular_Turrets/corpses.json msgid "broken disarmed defense bot" msgid_plural "broken disarmed defense bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "defensibot desarmado roto" +msgstr[1] "defensibots desarmados rotos" +msgstr[2] "defensibots desarmados rotos" #: data/mods/Aftershock/items/corpses.json msgid "broken medical bot" msgid_plural "broken medical bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "medicobot roto" +msgstr[1] "medicobots rotos" +msgstr[2] "medicobots rotos" #. ~ Description for broken medical bot #: data/mods/Aftershock/items/corpses.json @@ -192478,9 +192777,9 @@ msgstr "" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive bee-bot" msgid_plural "inactive bee-bots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "abejabot inactivo" +msgstr[1] "abejabots inactivos" +msgstr[2] "abejabots inactivos" #. ~ Description for inactive bee-bot #: data/mods/Aftershock/items/inactiverobot.json @@ -192564,9 +192863,9 @@ msgstr "" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive floating heater" msgid_plural "inactive floating heaters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "calentador flotante inactivo" +msgstr[1] "calentadores flotantes inactivos" +msgstr[2] "calentadores flotantes inactivos" #. ~ Description for inactive floating heater #: data/mods/Aftershock/items/inactiverobot.json @@ -192617,9 +192916,9 @@ msgstr "" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive pest hunter" msgid_plural "inactive pest hunters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cazapestes inactivo" +msgstr[1] "cazapestes inactivos" +msgstr[2] "cazapestes inactivos" #. ~ Description for inactive pest hunter #: data/mods/Aftershock/items/inactiverobot.json @@ -192649,9 +192948,9 @@ msgstr "" msgctxt "container" msgid "basin" msgid_plural "basins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bol" +msgstr[1] "bols" +msgstr[2] "bols" #. ~ Description for {'ctxt': 'container', 'str': 'basin'} #: data/mods/Aftershock/items/items.json @@ -192780,9 +193079,9 @@ msgstr "Es un pequeño perdigón de metal plateado, todavía tibio." #: data/mods/Aftershock/items/items.json msgid "nuclear fuel pellet" msgid_plural "nuclear fuel pellets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "perdigón de combustible nuclear" +msgstr[1] "perdigones de combustible nuclear" +msgstr[2] "perdigones de combustible nuclear" #. ~ Description for {'str': 'nuclear fuel pellet'} #: data/mods/Aftershock/items/items.json @@ -192792,9 +193091,9 @@ msgstr "Es un pequeño perdigón de material fisible. Manejar con cuidado." #: data/mods/Aftershock/items/items.json msgid "hazardous waste drum" msgid_plural "hazardous waste drums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "tambor de residuos peligrosos" +msgstr[1] "tambores de residuos peligrosos" +msgstr[2] "tambores de residuos peligrosos" #. ~ Description for {'str': 'hazardous waste drum'} #: data/mods/Aftershock/items/items.json @@ -192827,9 +193126,9 @@ msgstr[2] "" #: data/mods/Aftershock/items/items.json msgid "titanium" msgid_plural "titanium" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "titanio" +msgstr[1] "titanio" +msgstr[2] "titanio" #. ~ Description for {'str_sp': 'titanium'} #: data/mods/Aftershock/items/items.json @@ -192880,9 +193179,9 @@ msgstr "" #: data/mods/Aftershock/items/items.json msgid "titanium watch" msgid_plural "titanium watches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "reloj de titanio" +msgstr[1] "relojes de titanio" +msgstr[2] "relojes de titanio" #. ~ Description for {'str': 'titanium watch', 'str_pl': 'titanium watches'} #: data/mods/Aftershock/items/items.json @@ -192896,9 +193195,9 @@ msgstr "" #: data/mods/Aftershock/items/items.json msgid "titanium ring" msgid_plural "titanium rings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "anillo de titanio" +msgstr[1] "anillos de titanio" +msgstr[2] "anillos de titanio" #. ~ Description for {'str': 'titanium ring'} #: data/mods/Aftershock/items/items.json @@ -192920,9 +193219,9 @@ msgstr "" #: data/mods/Aftershock/items/mutagen.json msgid "mi-go serum" msgid_plural "mi-go serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de mi-go" +msgstr[1] "sueros de mi-go" +msgstr[2] "sueros de mi-go" #. ~ Description for mi-go serum #: data/mods/Aftershock/items/mutagen.json @@ -192936,9 +193235,9 @@ msgstr "" #: data/mods/Aftershock/items/mutagen.json msgid "mi-go mutagen" msgid_plural "mi-go mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de mi-go" +msgstr[1] "mutágenos de mi-go" +msgstr[2] "mutágenos de mi-go" #. ~ Description for mi-go mutagen #: data/mods/Aftershock/items/mutagen.json @@ -192951,9 +193250,9 @@ msgstr "" #: data/mods/Aftershock/items/mutagen.json msgid "mastodon serum" msgid_plural "mastodon serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de mastodonte" +msgstr[1] "sueros de mastodonte" +msgstr[2] "sueros de mastodonte" #. ~ Description for {'str': 'mastodon serum'} #. ~ Description for {'str': 'stego serum'} @@ -192970,9 +193269,9 @@ msgstr "" #: data/mods/Aftershock/items/mutagen.json msgid "mastodon mutagen" msgid_plural "mastodon mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de mastodonte" +msgstr[1] "mutágenos de mastodonte" +msgstr[2] "mutágenos de mastodonte" #. ~ Description for {'str': 'mastodon mutagen'} #. ~ Description for {'str': 'stego mutagen'} @@ -193032,9 +193331,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "dough" msgid_plural "doughs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "masa" +msgstr[1] "masas" +msgstr[2] "masas" #. ~ Description for dough #: data/mods/Aftershock/items/obsolete.json @@ -193049,9 +193348,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "hazardous environment suit" msgid_plural "hazardous environment suits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "traje para ambientes peligrosos" +msgstr[1] "trajes para ambientes peligrosos" +msgstr[2] "trajes para ambientes peligrosos" #. ~ Description for hazardous environment suit #: data/mods/Aftershock/items/obsolete.json @@ -193109,9 +193408,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "boot quiver" msgid_plural "boot quivers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aljaba bota" +msgstr[1] "aljabas bota" +msgstr[2] "aljabas bota" #. ~ Description for {'str': 'boot quiver'} #: data/mods/Aftershock/items/obsolete.json @@ -193127,9 +193426,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "quilt" msgid_plural "quilts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colcha" +msgstr[1] "colchas" +msgstr[2] "colchas" #. ~ Description for quilt #: data/mods/Aftershock/items/obsolete.json @@ -193143,9 +193442,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "patchwork quilt" msgid_plural "patchwork quilts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "colcha de retazos" +msgstr[1] "colchas de retazos" +msgstr[2] "colchas de retazos" #. ~ Description for patchwork quilt #: data/mods/Aftershock/items/obsolete.json @@ -193155,9 +193454,9 @@ msgstr "Es una enorme colcha hecha de pedazos de lana. Muy, muy abrigada." #: data/mods/Aftershock/items/obsolete.json msgid "survivor utility belt (holster)" msgid_plural "survivor utility belts (holster)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón de herramientas de supervivencia (funda)" +msgstr[1] "cinturones de herramientas de supervivencia (funda)" +msgstr[2] "cinturones de herramientas de supervivencia (funda)" #. ~ Description for {'str': 'survivor utility belt (holster)', 'str_pl': #. 'survivor utility belts (holster)'} @@ -193175,16 +193474,16 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "survivor utility belt (sheath)" msgid_plural "survivor utility belts (sheath)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón de herramientas de supervivencia (vaina)" +msgstr[1] "cinturones de herramientas de supervivencia (vaina)" +msgstr[2] "cinturones de herramientas de supervivencia (vaina)" #: data/mods/Aftershock/items/obsolete.json msgid "brigandine" msgid_plural "brigandines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brigantina" +msgstr[1] "brigantinas" +msgstr[2] "brigantinas" #. ~ Description for {'str': 'brigandine'} #: data/mods/Aftershock/items/obsolete.json @@ -193201,9 +193500,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "MBR vest (titanium)" msgid_plural "MBR vests (titanium)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "chaleco MBR (titanio)" +msgstr[1] "chalecos MBR (titanio)" +msgstr[2] "chalecos MBR (titanio)" #. ~ Description for {'str': 'MBR vest (titanium)', 'str_pl': 'MBR vests #. (titanium)'} @@ -193219,9 +193518,9 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "crafted brigandine" msgid_plural "crafted brigandines" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "brigantina artesanal" +msgstr[1] "brigantinas artesanales" +msgstr[2] "brigantinas artesanales" #. ~ Description for crafted brigandine #: data/mods/Aftershock/items/obsolete.json @@ -193746,9 +194045,9 @@ msgstr "" #: data/mods/Aftershock/items/weapons.json msgid "shoddy laser rifle" msgid_plural "shoddy laser rifles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "rifle láser de mala calidad" +msgstr[1] "rifles láser de mala calidad" +msgstr[2] "rifles láser de mala calidad" #: data/mods/Aftershock/items/weapons.json msgid "" @@ -194386,9 +194685,9 @@ msgstr[2] "eyectaplasma integrales" #: data/mods/Modular_Turrets/roboguns.json msgid "integral railgun" msgid_plural "integral railguns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cañón de riel integral" +msgstr[1] "cañones de riel integrales" +msgstr[2] "cañones de riel integrales" #: data/mods/Aftershock/items/gun/grenade.json msgid "40mm EMP grenade" @@ -195115,6 +195414,14 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -198791,9 +199098,9 @@ msgstr "" #: data/mods/CRT_EXPANSION/items/crt_ammo.json msgid "pulse round" msgid_plural "pulse rounds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho de pulso" +msgstr[1] "cartuchos de pulso" +msgstr[2] "cartuchos de pulso" #. ~ Description for pulse round #: data/mods/CRT_EXPANSION/items/crt_ammo.json @@ -200783,9 +201090,9 @@ msgstr "" #: data/mods/CRT_EXPANSION/mutations/vamp_mut_cat.json msgid "vampire mutagen" msgid_plural "vampire mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de vampiro" +msgstr[1] "mutágenos de vampiro" +msgstr[2] "mutágenos de vampiro" #. ~ Description for vampire mutagen #. ~ Description for wendigo mutagen @@ -200797,9 +201104,9 @@ msgstr "Es un cóctel de mutágeno con una etiqueta que dice 'C.R.I.T R&D'." #: data/mods/CRT_EXPANSION/mutations/vamp_mut_cat.json msgid "vampire serum" msgid_plural "vampire serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de vampiro" +msgstr[1] "sueros de vampiro" +msgstr[2] "sueros de vampiro" #. ~ Description for vampire serum #: data/mods/CRT_EXPANSION/mutations/vamp_mut_cat.json @@ -200883,16 +201190,16 @@ msgstr "Reclamado por la naturaleza." #: data/mods/CRT_EXPANSION/mutations/wendigo_mut_cat.json msgid "wendigo mutagen" msgid_plural "wendigo mutagens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mutágeno de wendigo" +msgstr[1] "mutágenos de wendigo" +msgstr[2] "mutágenos de wendigo" #: data/mods/CRT_EXPANSION/mutations/wendigo_mut_cat.json msgid "wendigo serum" msgid_plural "wendigo serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero de wendigo" +msgstr[1] "sueros de wendigo" +msgstr[2] "sueros de wendigo" #. ~ Description for wendigo serum #: data/mods/CRT_EXPANSION/mutations/wendigo_mut_cat.json @@ -201474,9 +201781,9 @@ msgstr "" #: data/mods/CrazyCataclysm/crazy_comestibles.json msgid "SpOreos" msgid_plural "SpOreos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "EspOreos" +msgstr[1] "EspOreos" +msgstr[2] "EspOreos" #. ~ Description for {'str_sp': 'SpOreos'} #: data/mods/CrazyCataclysm/crazy_comestibles.json @@ -201545,9 +201852,9 @@ msgstr "" #: data/mods/CrazyCataclysm/crazy_items.json msgid "Ionic Overload Generator" msgid_plural "Ionic Overload Generators" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Generador de Sobrecarga Iónica" +msgstr[1] "Generadores de Sobrecarga Iónica" +msgstr[2] "Generadores de Sobrecarga Iónica" #: data/mods/CrazyCataclysm/crazy_items.json msgid "" @@ -203898,9 +204205,9 @@ msgstr "" #: data/mods/DinoMod/items/egg.json msgid "dinosaur egg" msgid_plural "dinosaur eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de dinosaurio" +msgstr[1] "huevos de dinosaurio" +msgstr[2] "huevos de dinosaurio" #. ~ Description for dinosaur egg #: data/mods/DinoMod/items/egg.json @@ -203958,9 +204265,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "dilophosaurus egg" msgid_plural "dilophosaurus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de dilophosaurus" +msgstr[1] "huevos de dilophosaurus" +msgstr[2] "huevos de dilophosaurus" #: data/mods/DinoMod/items/egg.json msgid "ceratosaurus egg" @@ -203972,9 +204279,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "spinosaurus egg" msgid_plural "spinosaurus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de spinosaurus" +msgstr[1] "huevos de spinosaurus" +msgstr[2] "huevos de spinosaurus" #: data/mods/DinoMod/items/egg.json msgid "torvosaurus egg" @@ -203986,9 +204293,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "allosaurus egg" msgid_plural "allosaurus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de allosaurus" +msgstr[1] "huevos de allosaurus" +msgstr[2] "huevos de allosaurus" #: data/mods/DinoMod/items/egg.json msgid "acrocanthosaurus egg" @@ -204056,23 +204363,23 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "tyrannosaurus egg" msgid_plural "tyrannosaurus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de tyrannosaurus" +msgstr[1] "huevos de tyrannosaurus" +msgstr[2] "huevos de tyrannosaurus" #: data/mods/DinoMod/items/egg.json msgid "compsognathus egg" msgid_plural "compsognathus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de compsognathus" +msgstr[1] "huevos de compsognathus" +msgstr[2] "huevos de compsognathus" #: data/mods/DinoMod/items/egg.json msgid "gallimimus egg" msgid_plural "gallimimus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de gallimimus" +msgstr[1] "huevos de gallimimus" +msgstr[2] "huevos de gallimimus" #: data/mods/DinoMod/items/egg.json msgid "struthiomimus egg" @@ -204119,23 +204426,23 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "velociraptor egg" msgid_plural "velociraptor eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de velociraptor" +msgstr[1] "huevos de velociraptor" +msgstr[2] "huevos de velociraptor" #: data/mods/DinoMod/items/egg.json msgid "deinonychus egg" msgid_plural "deinonychus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de deinonychus" +msgstr[1] "huevos de deinonychus" +msgstr[2] "huevos de deinonychus" #: data/mods/DinoMod/items/egg.json msgid "utahraptor egg" msgid_plural "utahraptor eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de utahraptor" +msgstr[1] "huevos de utahraptor" +msgstr[2] "huevos de utahraptor" #: data/mods/DinoMod/items/egg.json msgid "dromaeosaurus egg" @@ -204154,9 +204461,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "eoraptor egg" msgid_plural "eoraptor eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de eoraptor" +msgstr[1] "huevos de eoraptor" +msgstr[2] "huevos de eoraptor" #: data/mods/DinoMod/items/egg.json msgid "sarahsaurus egg" @@ -204252,9 +204559,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "stegosaurus egg" msgid_plural "stegosaurus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de stegosaurus" +msgstr[1] "huevos de stegosaurus" +msgstr[2] "huevos de stegosaurus" #: data/mods/DinoMod/items/egg.json msgid "hesperosaurus egg" @@ -204322,9 +204629,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "ankylosaurus egg" msgid_plural "ankylosaurus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de ankylosaurus" +msgstr[1] "huevos de ankylosaurus" +msgstr[2] "huevos de ankylosaurus" #: data/mods/DinoMod/items/egg.json msgid "euoplocephalus egg" @@ -204406,9 +204713,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "parasaurolophus egg" msgid_plural "parasaurolophus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de parasaurolophus" +msgstr[1] "huevos de parasaurolophus" +msgstr[2] "huevos de parasaurolophus" #: data/mods/DinoMod/items/egg.json msgid "lambeosaurus egg" @@ -204441,9 +204748,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "pachycephalosaurus egg" msgid_plural "pachycephalosaurus eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de pachycephalosaurus" +msgstr[1] "huevos de pachycephalosaurus" +msgstr[2] "huevos de pachycephalosaurus" #: data/mods/DinoMod/items/egg.json msgid "aquilops egg" @@ -204532,9 +204839,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "triceratops egg" msgid_plural "triceratops eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de triceratops" +msgstr[1] "huevos de triceratops" +msgstr[2] "huevos de triceratops" #: data/mods/DinoMod/items/egg.json msgid "nanosaurus egg" @@ -204560,9 +204867,9 @@ msgstr[2] "" #: data/mods/DinoMod/items/egg.json msgid "dimorphodon egg" msgid_plural "dimorphodon eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de dimorphodon" +msgstr[1] "huevos de dimorphodon" +msgstr[2] "huevos de dimorphodon" #: data/mods/DinoMod/items/egg.json msgid "pteranodon egg" @@ -205404,6 +205711,14 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -214861,9 +215176,9 @@ msgstr "Es un conjunto de 52 cartas francesas, hechas para jugar al póquer." #: data/mods/Fuji_Structures/items/items_games.json msgid "deck of Sorcery cards" msgid_plural "decks of Sorcery cards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mazo de cartas Hechicería" +msgstr[1] "mazos de cartas Hechicería" +msgstr[2] "mazos de cartas Hechicería" #. ~ Description for {'str': 'deck of Sorcery cards', 'str_pl': 'decks of #. Sorcery cards'} @@ -214878,9 +215193,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Picturesque" msgid_plural "sets of Picturesque" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Pintoresco" +msgstr[1] "colección de Pintoresco" +msgstr[2] "colección de Pintoresco" #. ~ Description for {'str': 'Picturesque', 'str_pl': 'sets of Picturesque'} #: data/mods/Fuji_Structures/items/items_games.json @@ -214893,9 +215208,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Capitalism" msgid_plural "sets of Capitalism" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Capitalismo" +msgstr[1] "colección de Capitalismo" +msgstr[2] "colección de Capitalismo" #. ~ Description for {'str': 'Capitalism', 'str_pl': 'sets of Capitalism'} #: data/mods/Fuji_Structures/items/items_games.json @@ -214909,9 +215224,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Blobs and Bandits" msgid_plural "sets of Blobs and Bandits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Blobos y Bandidos" +msgstr[1] "colección de Blobos y Bandidos" +msgstr[2] "colección de Blobos y Bandidos" #. ~ Description for {'str': 'Blobs and Bandits', 'str_pl': 'sets of Blobs and #. Bandits'} @@ -214926,9 +215241,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Battlehammer" msgid_plural "sets of Battlehammer" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Battlehammer" +msgstr[1] "colección de Battlehammer" +msgstr[2] "colección de Battlehammer" #. ~ Description for {'str': 'Battlehammer', 'str_pl': 'sets of Battlehammer'} #: data/mods/Fuji_Structures/items/items_games.json @@ -214940,9 +215255,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Battlehammer 20k" msgid_plural "sets of Battlehammer 20k" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Battlehammer 20k" +msgstr[1] "colección de Battlehammer 20k" +msgstr[2] "colección de Battlehammer 20k" #. ~ Description for {'str': 'Battlehammer 20k', 'str_pl': 'sets of #. Battlehammer 20k'} @@ -214957,9 +215272,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Settlers of the Ranch" msgid_plural "sets of Settlers of the Ranch" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Colonizadores de Rancho" +msgstr[1] "colección de Colonizadores de Rancho" +msgstr[2] "colección de Colonizadores de Rancho" #. ~ Description for {'str': 'Settlers of the Ranch', 'str_pl': 'sets of #. Settlers of the Ranch'} @@ -214973,9 +215288,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Warships" msgid_plural "sets of Warships" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Buques de Guerra" +msgstr[1] "colección de Buques de Guerra" +msgstr[2] "colección de Buques de Guerra" #. ~ Description for {'str': 'Warships', 'str_pl': 'sets of Warships'} #: data/mods/Fuji_Structures/items/items_games.json @@ -214989,9 +215304,9 @@ msgstr "" #: data/mods/Fuji_Structures/items/items_games.json msgid "Murder Mystery" msgid_plural "sets of Murder Mystery" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Asesinato Misterioso" +msgstr[1] "colección de Asesinato Misterioso" +msgstr[2] "colección de Asesinato Misterioso" #. ~ Description for {'str': 'Murder Mystery', 'str_pl': 'sets of Murder #. Mystery'} @@ -215526,73 +215841,73 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "pistol ammo, ball (reloaded)" msgid_plural "pistol ammo, ball (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de pistola, bola (recargada)" +msgstr[1] "munición de pistola, bola (recargada)" +msgstr[2] "munición de pistola, bola (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "pistol ammo, JHP (reloaded)" msgid_plural "pistol ammo, JHP (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de pistola, JHP (recargada)" +msgstr[1] "munición de pistola, JHP (recargada)" +msgstr[2] "munición de pistola, JHP (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "tiny pistol ammo, ball (reloaded)" msgid_plural "tiny pistol ammo, ball (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de pistola pequeña, bola (recargada)" +msgstr[1] "munición de pistola pequeña, bola (recargada)" +msgstr[2] "munición de pistola pequeña, bola (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "tiny pistol ammo, JHP (reloaded)" msgid_plural "tiny pistol ammo, JHP (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de pistola pequeña, JHP (recargada)" +msgstr[1] "munición de pistola pequeña, JHP (recargada)" +msgstr[2] "munición de pistola pequeña, JHP (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "magnum ammo, ball (reloaded)" msgid_plural "magnum ammo, ball (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de magnum, bola (recargada)" +msgstr[1] "munición de magnum, bola (recargada)" +msgstr[2] "munición de magnum, bola (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "magnum ammo, JHP (reloaded)" msgid_plural "magnum ammo, JHP (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de magnum, JHP (recargada)" +msgstr[1] "munición de magnum, JHP (recargada)" +msgstr[2] "munición de magnum, JHP (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, buckshot (reloaded)" msgid_plural "shotshell, buckshot (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, perdigones grandes (recargado)" +msgstr[1] "cartucho, perdigones grandes (recargado)" +msgstr[2] "cartucho, perdigones grandes (recargado)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, birdshot (reloaded)" msgid_plural "shotshell, birdshot (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, perdigones pequeños (recargado)" +msgstr[1] "cartucho, perdigones pequeños (recargado)" +msgstr[2] "cartucho, perdigones pequeños (recargado)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, slug (reloaded)" msgid_plural "shotshell, slug (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, posta (recargado)" +msgstr[1] "cartucho, posta (recargado)" +msgstr[2] "cartucho, posta (recargado)" #: data/mods/Generic_Guns/ammo/obsolete.json #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, junk" msgid_plural "shotshell, junk" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, chatarra" +msgstr[1] "cartucho, chatarra" +msgstr[2] "cartucho, chatarra" #: data/mods/Generic_Guns/ammo/obsolete.json #: data/mods/Generic_Guns/ammo/shot.json @@ -215619,16 +215934,16 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, pyrotechnical (reloaded)" msgid_plural "shotshell, pyrotechnical (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, pirotecnia (recargado)" +msgstr[1] "cartucho, pirotecnia (recargado)" +msgstr[2] "cartucho, pirotecnia (recargado)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, AP" msgid_plural "rifle ammo, AP" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de rifle, AP" +msgstr[1] "munición de rifle, AP" +msgstr[2] "munición de rifle, AP" #. ~ Description for {'str_sp': 'rifle ammo, AP'} #: data/mods/Generic_Guns/ammo/obsolete.json @@ -215648,30 +215963,30 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, ball (reloaded)" msgid_plural "rifle ammo, ball (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de rifle, bola (recargada)" +msgstr[1] "munición de rifle, bola (recargada)" +msgstr[2] "munición de rifle, bola (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, AP (reloaded)" msgid_plural "rifle ammo, AP (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de rifle, AP (recargada)" +msgstr[1] "munición de rifle, AP (recargada)" +msgstr[2] "munición de rifle, AP (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, AP (black powder)" msgid_plural "rifle ammo, AP (black powder)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de rifle, AP (pólvora)" +msgstr[1] "munición de rifle, AP (pólvora)" +msgstr[2] "munición de rifle, AP (pólvora)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "huge rifle ammo, AP" msgid_plural "huge rifle ammo, AP" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de rifle grande, AP" +msgstr[1] "munición de rifle grande, AP" +msgstr[2] "munición de rifle grande, AP" #. ~ Description for {'str_sp': 'huge rifle ammo, AP'} #: data/mods/Generic_Guns/ammo/obsolete.json @@ -215690,16 +216005,16 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "huge rifle ammo, ball (reloaded)" msgid_plural "huge rifle ammo, ball (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de rifle grande, bola (recargada)" +msgstr[1] "munición de rifle grande, bola (recargada)" +msgstr[2] "munición de rifle grande, bola (recargada)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "huge rifle ammo, AP (reloaded)" msgid_plural "huge rifle ammo, AP (reloaded)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "munición de rifle grande, AP (recargada)" +msgstr[1] "munición de rifle grande, AP (recargada)" +msgstr[2] "munición de rifle grande, AP (recargada)" #: data/mods/Generic_Guns/ammo/pistol.json msgid "9mm, FMJ" @@ -216046,9 +216361,9 @@ msgstr[2] "" #: data/mods/Generic_Guns/ammo/rocket.json msgid "rocket, antipersonnel" msgid_plural "rocket, antipersonnel" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil, antipersonal" +msgstr[1] "misil, antipersonal" +msgstr[2] "misil, antipersonal" #. ~ Description for {'str_sp': 'rocket, antipersonnel'} #: data/mods/Generic_Guns/ammo/rocket.json @@ -216062,9 +216377,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/rocket.json msgid "rocket, multipurpose" msgid_plural "rocket, multipurpose" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil, multipropósito" +msgstr[1] "misil, multipropósito" +msgstr[2] "misil, multipropósito" #. ~ Description for {'str_sp': 'rocket, multipurpose'} #: data/mods/Generic_Guns/ammo/rocket.json @@ -216080,9 +216395,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/rocket.json msgid "rocket, smoke" msgid_plural "rocket, smoke" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "misil, humo" +msgstr[1] "misil, humo" +msgstr[2] "misil, humo" #. ~ Description for {'str_sp': 'rocket, smoke'} #: data/mods/Generic_Guns/ammo/rocket.json @@ -216098,23 +216413,23 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, buckshot" msgid_plural "shotshell, buckshot" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, perdigones grandes" +msgstr[1] "cartucho, perdigones grandes" +msgstr[2] "cartucho, perdigones grandes" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, beanbag" msgid_plural "shotshell, beanbag" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, no letal" +msgstr[1] "cartucho, no letal" +msgstr[2] "cartucho, no letal" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, birdshot" msgid_plural "shotshell, birdshot" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, perdigones pequeños" +msgstr[1] "cartucho, perdigones pequeños" +msgstr[2] "cartucho, perdigones pequeños" #. ~ Description for {'str_sp': 'shotshell, birdshot'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216128,9 +216443,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, slug" msgid_plural "shotshell, slug" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, posta" +msgstr[1] "cartucho, posta" +msgstr[2] "cartucho, posta" #. ~ Description for {'str_sp': 'shotshell, slug'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216147,9 +216462,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, pyrotechnical" msgid_plural "shotshell, pyrotechnical" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, pirotecnia" +msgstr[1] "cartucho, pirotecnia" +msgstr[2] "cartucho, pirotecnia" #. ~ Description for {'str_sp': 'shotshell, pyrotechnical'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216165,9 +216480,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, buckshot (black powder)" msgid_plural "shotshell, buckshot (black powder)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, perdigones grandes (pólvora)" +msgstr[1] "cartucho, perdigones grandes (pólvora)" +msgstr[2] "cartucho, perdigones grandes (pólvora)" #. ~ Description for {'str_sp': 'shotshell, buckshot (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216180,9 +216495,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, birdshot (black powder)" msgid_plural "shotshell, birdshot (black powder)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, perdigones pequeños (pólvora)" +msgstr[1] "cartucho, perdigones pequeños (pólvora)" +msgstr[2] "cartucho, perdigones pequeños (pólvora)" #. ~ Description for {'str_sp': 'shotshell, birdshot (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216195,9 +216510,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, slug (black powder)" msgid_plural "shotshell, slug (black powder)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, posta (pólvora)" +msgstr[1] "cartucho, posta (pólvora)" +msgstr[2] "cartucho, posta (pólvora)" #. ~ Description for {'str_sp': 'shotshell, slug (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216211,9 +216526,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, pyrotechnical (black powder)" msgid_plural "shotshell, pyrotechnical (black powder)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, pirotecnia (pólvora)" +msgstr[1] "cartucho, pirotecnia (pólvora)" +msgstr[2] "cartucho, pirotecnia (pólvora)" #. ~ Description for {'str_sp': 'shotshell, pyrotechnical (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216227,9 +216542,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, flechette (black powder)" msgid_plural "shotshell, flechette (black powder)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, dardos perforantes (pólvora)" +msgstr[1] "cartucho, dardos perforantes (pólvora)" +msgstr[2] "cartucho, dardos perforantes (pólvora)" #. ~ Description for {'str_sp': 'shotshell, flechette (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216243,9 +216558,9 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, junk (black powder)" msgid_plural "shotshell, junk (black powder)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cartucho, chatarra (pólvora)" +msgstr[1] "cartucho, chatarra (pólvora)" +msgstr[2] "cartucho, chatarra (pólvora)" #. ~ Description for {'str_sp': 'shotshell, junk (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -216579,9 +216894,9 @@ msgstr "" #: data/mods/Generic_Guns/firearms/pistol.json msgid "submachine gun" msgid_plural "submachine guns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "subfusil" +msgstr[1] "subfusiles" +msgstr[2] "subfusiles" #: data/mods/Generic_Guns/firearms/pistol.json #: data/mods/Generic_Guns/firearms/sniper.json @@ -217811,9 +218126,9 @@ msgstr "" #: data/mods/Magiclysm/bionics.json data/mods/Magiclysm/items/bionics.json msgid "Blood Power Generator CBM" msgid_plural "Blood Power Generator CBMs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "MCB Generador de Energía a Sangre" +msgstr[1] "MCB Generador de Energía a Sangre" +msgstr[2] "MCB Generador de Energía a Sangre" #. ~ Description for {'str': 'Blood Power Generator CBM'} #: data/mods/Magiclysm/bionics.json @@ -218337,6 +218652,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -218472,6 +218792,27 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -220697,9 +221038,9 @@ msgstr "" #: data/mods/Magiclysm/items/alchemy_items.json msgid "copper infusion bracelet" msgid_plural "copper infusion bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de cobre de infusión" +msgstr[1] "pulseras de cobre de infusión" +msgstr[2] "pulseras de cobre de infusión" #. ~ Description for {'str': 'copper infusion bracelet'} #. ~ Description for {'str': 'silver infusion bracelet'} @@ -220714,16 +221055,16 @@ msgstr "" #: data/mods/Magiclysm/items/alchemy_items.json msgid "silver infusion bracelet" msgid_plural "silver infusion bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pulsera de plata de infusión" +msgstr[1] "pulseras de plata de infusión" +msgstr[2] "pulseras de plata de infusión" #: data/mods/Magiclysm/items/alchemy_items.json msgid "copper circlet" msgid_plural "copper circlets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "diadema de cobre" +msgstr[1] "diademas de cobre" +msgstr[2] "diademas de cobre" #. ~ Description for {'str': 'copper circlet'} #: data/mods/Magiclysm/items/alchemy_items.json @@ -220751,9 +221092,9 @@ msgstr "" #: data/mods/Magiclysm/items/alchemy_items.json msgid "potion starter" msgid_plural "potion starters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "poción de inicio" +msgstr[1] "pociones de inicio" +msgstr[2] "pociones de inicio" #. ~ Description for potion starter #: data/mods/Magiclysm/items/alchemy_items.json @@ -220767,9 +221108,9 @@ msgstr "" #: data/mods/Magiclysm/items/alchemy_items.json msgid "superior potion starter" msgid_plural "superior potion starters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "poción superior de inicio" +msgstr[1] "pociones superior de inicio" +msgstr[2] "pociones superior de inicio" #. ~ Description for superior potion starter #: data/mods/Magiclysm/items/alchemy_items.json @@ -220783,9 +221124,9 @@ msgstr "" #: data/mods/Magiclysm/items/alchemy_items.json msgid "large adrenal gland" msgid_plural "large adrenal glands" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "glándula suprarrenal grande" +msgstr[1] "glándulas suprarrenales grandes" +msgstr[2] "glándulas suprarrenales grandes" #. ~ Description for {'str': 'large adrenal gland'} #: data/mods/Magiclysm/items/alchemy_items.json @@ -220875,9 +221216,9 @@ msgstr "" #: data/mods/Magiclysm/items/alchemy_items.json msgid "dragon essence" msgid_plural "dragon essences" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "esencia de dragón" +msgstr[1] "esencias de dragón" +msgstr[2] "esencias de dragón" #. ~ Description for dragon essence #: data/mods/Magiclysm/items/alchemy_items.json @@ -220949,9 +221290,9 @@ msgstr "" #: data/mods/Magiclysm/items/ammo_types.json msgid "alumentum" msgid_plural "alumentum" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "alumentum" +msgstr[1] "alumentum" +msgstr[2] "alumentum" #. ~ Description for {'str_sp': 'alumentum'} #: data/mods/Magiclysm/items/alchemy_items.json @@ -220983,17 +221324,17 @@ msgstr "" #: data/mods/Magiclysm/items/fuel.json msgid "dragon blood" msgid_plural "dragon blood" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sangre de dragón" +msgstr[1] "sangre de dragón" +msgstr[2] "sangre de dragón" #: data/mods/Magiclysm/items/ammo_types.json #: data/mods/Magiclysm/items/fuel.json msgid "tainted blood" msgid_plural "tainted blood" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sangre contaminada" +msgstr[1] "sangre contaminada" +msgstr[2] "sangre contaminada" #: data/mods/Magiclysm/items/ammo_types.json #: data/mods/Magiclysm/items/fuel.json @@ -221007,9 +221348,9 @@ msgstr[2] "" #: data/mods/Magiclysm/items/archery.json msgid "orichalcum arrow" msgid_plural "orichalcum arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "flecha de oricalco" +msgstr[1] "flechas de oricalco" +msgstr[2] "flechas de oricalco" #: data/mods/Magiclysm/items/ammo_types.json msgid "mercury" @@ -221043,9 +221384,9 @@ msgstr "" #: data/mods/Magiclysm/items/armor.json msgid "pair of demon chitin arm guards" msgid_plural "pairs of demon chitin arm guards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de mangas de quitina demoníaca" +msgstr[1] "pares de mangas de quitina demoníaca" +msgstr[2] "pares de mangas de quitina demoníaca" #. ~ Description for {'str': 'pair of demon chitin arm guards', 'str_pl': #. 'pairs of demon chitin arm guards'} @@ -221061,9 +221402,9 @@ msgstr "" #: data/mods/Magiclysm/items/armor.json msgid "demon chitin armor" msgid_plural "demon chitin armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura de quitina demoníaca" +msgstr[1] "armaduras de quitina demoníaca" +msgstr[2] "armaduras de quitina demoníaca" #. ~ Description for {'str': 'demon chitin armor'} #: data/mods/Magiclysm/items/armor.json @@ -221078,9 +221419,9 @@ msgstr "" #: data/mods/Magiclysm/items/armor.json msgid "demon chitin helmet" msgid_plural "demon chitin helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casco de quitina demoníaca" +msgstr[1] "cascos de quitina demoníaca" +msgstr[2] "cascos de quitina demoníaca" #. ~ Description for {'str': 'demon chitin helmet'} #: data/mods/Magiclysm/items/armor.json @@ -221095,9 +221436,9 @@ msgstr "" #: data/mods/Magiclysm/items/armor.json msgid "pair of demon chitin gauntlets" msgid_plural "pairs of demon chitin gauntlets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes de quitina demoníaca" +msgstr[1] "pares de guantes de quitina demoníaca" +msgstr[2] "pares de guantes de quitina demoníaca" #. ~ Description for {'str': 'pair of demon chitin gauntlets', 'str_pl': #. 'pairs of demon chitin gauntlets'} @@ -221113,9 +221454,9 @@ msgstr "" #: data/mods/Magiclysm/items/armor.json msgid "pair of demon chitin boots" msgid_plural "pairs of demon chitin boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas de quitina demoníaca" +msgstr[1] "pares de botas de quitina demoníaca" +msgstr[2] "pares de botas de quitina demoníaca" #. ~ Description for {'str': 'pair of demon chitin boots', 'str_pl': 'pairs of #. demon chitin boots'} @@ -221203,9 +221544,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "raw black dragon hide" msgid_plural "raw black dragon hides" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pellejo crudo de dragón negro" +msgstr[1] "pellejos crudos de dragón negro" +msgstr[2] "pellejos crudos de dragón negro" #. ~ Description for raw black dragon hide #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221260,9 +221601,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of black dragonscale boots" msgid_plural "pairs of black dragonscale boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas negras de escamas de dragón" +msgstr[1] "pares de botas negras de escamas de dragón" +msgstr[2] "pares de botas negras de escamas de dragón" #. ~ Description for {'str': 'pair of black dragonscale boots', 'str_pl': #. 'pairs of black dragonscale boots'} @@ -221292,9 +221633,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "black dragonscale helmet" msgid_plural "black dragonscale helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casco negro de escamas de dragón" +msgstr[1] "cascos negros de escamas de dragón" +msgstr[2] "cascos negros de escamas de dragón" #. ~ Description for black dragonscale helmet #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221308,9 +221649,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "black dragonhide helmet" msgid_plural "black dragonhide helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casco negro de pellejo de dragón" +msgstr[1] "cascos negros de pellejo de dragón" +msgstr[2] "cascos negros de pellejo de dragón" #. ~ Description for black dragonhide helmet #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221324,9 +221665,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "black dragonscale armor" msgid_plural "black dragonscale armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura negra de escamas de dragón" +msgstr[1] "armaduras negras de escamas de dragón" +msgstr[2] "armaduras negras de escamas de dragón" #. ~ Description for black dragonscale armor #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221342,9 +221683,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "black dragonhide armor" msgid_plural "black dragonhide armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura negra de pellejo de dragón" +msgstr[1] "armaduras negras de pellejo de dragón" +msgstr[2] "armaduras negras de pellejo de dragón" #. ~ Description for black dragonhide armor #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221375,16 +221716,16 @@ msgstr "Es un par de guantes resistentes hechos de escamas negras de dragón." #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of black dragonhide gloves" msgid_plural "pairs of black dragonhide gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes negros de pellejo de dragón" +msgstr[1] "pares de guantes negros de pellejo de dragón" +msgstr[2] "pares de guantes negros de pellejo de dragón" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonscale boots" msgid_plural "pairs of XL black dragonscale boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas XL negras de escamas de dragón" +msgstr[1] "pares de botas XL negras de escamas de dragón" +msgstr[2] "pares de botas XL negras de escamas de dragón" #. ~ Description for {'str': 'pair of XL black dragonscale boots', 'str_pl': #. 'pairs of XL black dragonscale boots'} @@ -221400,9 +221741,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonhide boots" msgid_plural "pairs of XL black dragonhide boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas XL negras de pellejo de dragón" +msgstr[1] "pares de botas XL negras de pellejo de dragón" +msgstr[2] "pares de botas XL negras de pellejo de dragón" #. ~ Description for {'str': 'pair of XL black dragonhide boots', 'str_pl': #. 'pairs of XL black dragonhide boots'} @@ -221418,9 +221759,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonscale gauntlets" msgid_plural "pairs of XL black dragonscale gauntlets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes negros XL de escamas de dragón" +msgstr[1] "pares de guantes negros XL de escamas de dragón" +msgstr[2] "pares de guantes negros XL de escamas de dragón" #. ~ Description for {'str': 'pair of XL black dragonscale gauntlets', #. 'str_pl': 'pairs of XL black dragonscale gauntlets'} @@ -221435,9 +221776,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonhide gloves" msgid_plural "pairs of XL black dragonhide gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes negros XL de pellejo de dragón" +msgstr[1] "pares de guantes negros XL de pellejo de dragón" +msgstr[2] "pares de guantes negros XL de pellejo de dragón" #. ~ Description for {'str': 'pair of XL black dragonhide gloves', 'str_pl': #. 'pairs of XL black dragonhide gloves'} @@ -221455,9 +221796,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonscale helmet" msgid_plural "XL black dragonscale helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casco negro XL de escamas de dragón" +msgstr[1] "cascos negros XL de escamas de dragón" +msgstr[2] "cascos negros XL de escamas de dragón" #. ~ Description for {'str': 'XL black dragonscale helmet'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221473,9 +221814,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonhide helmet" msgid_plural "XL black dragonhide helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "casco negro XL de pellejo de dragón" +msgstr[1] "cascos negros XL de pellejo de dragón" +msgstr[2] "cascos negros XL de pellejo de dragón" #. ~ Description for {'str': 'XL black dragonhide helmet'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221491,9 +221832,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonscale armor" msgid_plural "XL black dragonscale armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura negra XL de escamas de dragón" +msgstr[1] "armaduras negras XL de escamas de dragón" +msgstr[2] "armaduras negras XL de escamas de dragón" #. ~ Description for {'str': 'XL black dragonscale armor'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221509,9 +221850,9 @@ msgstr "" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonhide armor" msgid_plural "XL black dragonhide armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura negra XL de pellejo de dragón" +msgstr[1] "armaduras negras XL de pellejo de dragón" +msgstr[2] "armaduras negras XL de pellejo de dragón" #. ~ Description for {'str': 'XL black dragonhide armor'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -221670,9 +222011,9 @@ msgstr "" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "zombie voodoo doll" msgid_plural "zombie voodoo dolls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "muñeco vudú zombi" +msgstr[1] "muñecos vudú zombi" +msgstr[2] "muñecos vudú zombi" #. ~ Description for zombie voodoo doll #: data/mods/Magiclysm/items/cast_spell_items.json @@ -221689,9 +222030,9 @@ msgstr "" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "ossified voodoo doll" msgid_plural "ossified voodoo dolls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "muñeco vudú osificado" +msgstr[1] "muñecos vudú osificado" +msgstr[2] "muñecos vudú osificado" #. ~ Description for ossified voodoo doll #: data/mods/Magiclysm/items/cast_spell_items.json @@ -221709,9 +222050,9 @@ msgstr "" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "cougar voodoo doll" msgid_plural "cougar voodoo dolls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "muñeco vudú puma" +msgstr[1] "muñecos vudú puma" +msgstr[2] "muñecos vudú puma" #. ~ Description for cougar voodoo doll #: data/mods/Magiclysm/items/cast_spell_items.json @@ -221728,9 +222069,9 @@ msgstr "" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Twisted Restoration" msgid_plural "potions of Twisted Restoration" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "poción Restoración Retorcida" +msgstr[1] "pociones Restoración Retorcida" +msgstr[2] "pociones Restoración Retorcida" #. ~ Description for {'str': 'potion of Twisted Restoration', 'str_pl': #. 'potions of Twisted Restoration'} @@ -221747,9 +222088,9 @@ msgstr "" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Improved Twisted Restoration" msgid_plural "potions of Improved Twisted Restoration" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "poción Restoración Retorcida Mejorada" +msgstr[1] "pociones Restoración Retorcida Mejorada" +msgstr[2] "pociones Restoración Retorcida Mejorada" #. ~ Description for {'str': 'potion of Improved Twisted Restoration', #. 'str_pl': 'potions of Improved Twisted Restoration'} @@ -221895,9 +222236,9 @@ msgstr "" #: data/mods/Magiclysm/items/comestibles.json msgid "owlbear egg" msgid_plural "owlbear eggs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "huevo de oso lechuza" +msgstr[1] "huevos de oso lechuza" +msgstr[2] "huevos de oso lechuza" #. ~ Description for owlbear egg #: data/mods/Magiclysm/items/comestibles.json @@ -221917,9 +222258,9 @@ msgstr "" #: data/mods/Magiclysm/items/comestibles.json msgid "owlbear egg yolk" msgid_plural "owlbear egg yolks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "yema de huevo de oso lechuza" +msgstr[1] "yemas de huevo de oso lechuza" +msgstr[2] "yemas de huevo de oso lechuza" #. ~ Description for owlbear egg yolk #: data/mods/Magiclysm/items/comestibles.json @@ -221929,9 +222270,9 @@ msgstr "Es el líquido interior de un huevo de oso lechuza. Buena comida." #: data/mods/Magiclysm/items/comestibles.json msgid "hairball" msgid_plural "hairballs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bola de pelo" +msgstr[1] "bolas de pelo" +msgstr[2] "bolas de pelo" #. ~ Description for {'str': 'hairball'} #: data/mods/Magiclysm/items/comestibles.json @@ -221944,9 +222285,9 @@ msgstr "" #: data/mods/Magiclysm/items/comestibles.json msgid "dragon meat" msgid_plural "dragon meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carne de dragón" +msgstr[1] "carne de dragón" +msgstr[2] "carne de dragón" #. ~ Description for {'str_sp': 'dragon meat'} #: data/mods/Magiclysm/items/comestibles.json @@ -221962,9 +222303,9 @@ msgstr "" #: data/mods/Magiclysm/items/comestibles.json msgid "scream mushroom" msgid_plural "scream mushrooms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "grithongo" +msgstr[1] "grithongos" +msgstr[2] "grithongos" #. ~ Description for scream mushroom #: data/mods/Magiclysm/items/comestibles.json @@ -221977,9 +222318,9 @@ msgstr "" #: data/mods/Magiclysm/items/comestibles.json msgid "purified meat" msgid_plural "purified meats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carne purificada" +msgstr[1] "carnes purificadas" +msgstr[2] "carnes purificadas" #. ~ Description for purified meat #: data/mods/Magiclysm/items/comestibles.json @@ -221993,9 +222334,9 @@ msgstr "" #: data/mods/Magiclysm/items/comestibles.json msgid "impure meat" msgid_plural "impure meats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "carne impura" +msgstr[1] "carnes impuras" +msgstr[2] "carnes impuras" #. ~ Description for impure meat #: data/mods/Magiclysm/items/comestibles.json @@ -222067,16 +222408,16 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted.json msgid "belt of strength +2" msgid_plural "belts of strength +2" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón de fuerza +2" +msgstr[1] "cinturones de fuerza +2" +msgstr[2] "cinturones de fuerza +2" #: data/mods/Magiclysm/items/enchanted.json msgid "belt of haste" msgid_plural "belts of haste" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón de apuro" +msgstr[1] "cinturones de apuro" +msgstr[2] "cinturones de apuro" #: data/mods/Magiclysm/items/enchanted.json msgid "lesser staff of the magi" @@ -222096,9 +222437,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted.json msgid "wizard hat" msgid_plural "wizard hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "sombrero de mago" +msgstr[1] "sombreros de mago" +msgstr[2] "sombreros de mago" #. ~ Description for wizard hat #: data/mods/Magiclysm/items/enchanted.json @@ -222193,9 +222534,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_belts.json msgid "technomancer's toolbelt" msgid_plural "technomancer's toolbelts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cinturón de herramientas de tecnomante" +msgstr[1] "cinturones de herramientas de tecnomante" +msgstr[2] "cinturones de herramientas de tecnomante" #. ~ Description for {'str': "technomancer's toolbelt"} #: data/mods/Magiclysm/items/enchanted_belts.json @@ -222255,9 +222596,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_boots.json msgid "seven league boots" msgid_plural "pairs of seven league boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas de siete leguas" +msgstr[1] "pares de botas de siete leguas" +msgstr[2] "pares de botas de siete leguas" #. ~ Description for {'str': 'seven league boots', 'str_pl': 'pairs of seven #. league boots'} @@ -222276,9 +222617,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_boots.json msgid "boots of haste" msgid_plural "pairs of boots of haste" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas de apuro" +msgstr[1] "pares de botas de apuro" +msgstr[2] "pares de botas de apuro" #: data/mods/Magiclysm/items/enchanted_boots.json msgid "escape boots" @@ -222298,9 +222639,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_boots.json msgid "boots of grounding" msgid_plural "pairs of boots of grounding" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de botas aislantes" +msgstr[1] "pares de botas aislantes" +msgstr[2] "pares de botas aislantes" #. ~ Description for {'str': 'boots of grounding', 'str_pl': 'pairs of boots #. of grounding'} @@ -222569,6 +222910,20 @@ msgstr[0] "maza +2s" msgstr[1] "mazas +2s" msgstr[2] "mazas +2s" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -222808,6 +223163,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -222815,6 +223171,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -222878,6 +223235,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -222885,6 +223243,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -223087,6 +223446,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -223306,9 +223679,9 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_misc.json msgid "endless flask" msgid_plural "endless flasks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "frasco sin fin" +msgstr[1] "frascos sin fin" +msgstr[2] "frascos sin fin" #. ~ Use action msg for {'str': 'endless flask'}. #: data/mods/Magiclysm/items/enchanted_misc.json @@ -224035,6 +224408,90 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -224535,9 +224992,9 @@ msgstr[2] "" #: data/mods/Magiclysm/items/ethereal_items.json msgid "pair of magical armored stone gauntlets" msgid_plural "pairs of magical armored stone gauntlets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "par de guantes mágicos de piedra" +msgstr[1] "pares de guantes mágicos de piedra" +msgstr[2] "pares de guantes mágicos de piedra" #. ~ Description for {'str': 'pair of magical armored stone gauntlets', #. 'str_pl': 'pairs of magical armored stone gauntlets'} @@ -224564,9 +225021,9 @@ msgstr "" #: data/mods/Magiclysm/items/ethereal_items.json msgid "magic lamp" msgid_plural "magic lamps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lámpara mágica" +msgstr[1] "lámparas mágicas" +msgstr[2] "lámparas mágicas" #. ~ Description for magic lamp #: data/mods/Magiclysm/items/ethereal_items.json @@ -224576,9 +225033,9 @@ msgstr "Es una fuente de luz mágica que ilumina un área pequeña." #: data/mods/Magiclysm/items/ethereal_items.json msgid "magic light" msgid_plural "magic lights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "luz mágica" +msgstr[1] "luces mágicas" +msgstr[2] "luces mágicas" #. ~ Description for magic light #: data/mods/Magiclysm/items/ethereal_items.json @@ -224588,9 +225045,9 @@ msgstr "Es una pequeña luz mágica que podés usar para leer." #: data/mods/Magiclysm/items/ethereal_items.json msgid "large shield of magical ice" msgid_plural "large shields of magical ice" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "escudo grande de hielo mágico" +msgstr[1] "escudos grandes de hielo mágico" +msgstr[2] "escudos grandes de hielo mágico" #. ~ Description for {'str': 'large shield of magical ice', 'str_pl': 'large #. shields of magical ice'} @@ -224603,9 +225060,9 @@ msgstr "" #: data/mods/Magiclysm/items/ethereal_items.json msgid "slick icy coatings" msgid_plural "slick icy coatings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "coberturas de hielo resbaladizo" +msgstr[1] "coberturas de hielo resbaladizo" +msgstr[2] "coberturas de hielo resbaladizo" #. ~ Description for {'str_sp': 'slick icy coatings'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -224663,9 +225120,9 @@ msgstr "" #: data/mods/Magiclysm/items/ethereal_items.json msgid "flesh pouch" msgid_plural "flesh pouches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "bolsa de carne" +msgstr[1] "bolsas de carne" +msgstr[2] "bolsas de carne" #. ~ Description for {'str': 'flesh pouch', 'str_pl': 'flesh pouches'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -224762,9 +225219,9 @@ msgstr "" #: data/mods/Magiclysm/items/ethereal_items.json msgid "acid resistance aura" msgid_plural "acid resistance auras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aura de resistencia al ácido" +msgstr[1] "auras de resistencia al ácido" +msgstr[2] "auras de resistencia al ácido" #. ~ Description for {'str': 'acid resistance aura'} #. ~ Description for greater acid resistance aura @@ -224775,16 +225232,16 @@ msgstr "Es una capa envolvente e invisible que protege contra el ácido." #: data/mods/Magiclysm/items/ethereal_items.json msgid "greater acid resistance aura" msgid_plural "greater acid resistance auras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aura de gran resistencia al ácido" +msgstr[1] "auras de gran resistencia al ácido" +msgstr[2] "auras de gran resistencia al ácido" #: data/mods/Magiclysm/items/ethereal_items.json msgid "frost armor" msgid_plural "frost armor" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "armadura de escarcha" +msgstr[1] "armaduras de escarcha" +msgstr[2] "armaduras de escarcha" #. ~ Description for {'str_sp': 'frost armor'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -224794,9 +225251,9 @@ msgstr "Es una fina capa de hielo mágico que cubre el cuerpo entero." #: data/mods/Magiclysm/items/ethereal_items.json msgid "stoneskin coating" msgid_plural "stoneskin coating" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cobertura de piedra" +msgstr[1] "cobertura de piedra" +msgstr[2] "cobertura de piedra" #. ~ Description for {'str_sp': 'stoneskin coating'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -224810,9 +225267,9 @@ msgstr "" #: data/mods/Magiclysm/items/ethereal_items.json msgid "overcharge burn" msgid_plural "overcharge burns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "quemadura de sobrecarga" +msgstr[1] "quemaduras de sobrecarga" +msgstr[2] "quemaduras de sobrecarga" #. ~ Description for {'str': 'overcharge burn'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -224822,9 +225279,9 @@ msgstr "Ay, ¡esto es muy elegante! Pero ya va a pasar, ¿no?" #: data/mods/Magiclysm/items/ethereal_items.json msgid "aura of protection" msgid_plural "auras of protection" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "aura de protección" +msgstr[1] "auras de protección" +msgstr[2] "auras de protección" #. ~ Description for {'str': 'aura of protection', 'str_pl': 'auras of #. protection'} @@ -224866,9 +225323,9 @@ msgstr "" #: data/mods/Magiclysm/items/mana_crystals.json msgid "crystallized mana" msgid_plural "crystallized mana" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "maná cristalizado" +msgstr[1] "maná cristalizado" +msgstr[2] "maná cristalizado" #. ~ Description for {'str_sp': 'crystallized mana'} #: data/mods/Magiclysm/items/mana_crystals.json @@ -225002,9 +225459,9 @@ msgstr "" #: data/mods/Magiclysm/items/metals.json msgid "lump of orichalcum" msgid_plural "lumps of orichalcum" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "conglomerado de oricalco" +msgstr[1] "conglomerados de oricalco" +msgstr[2] "conglomerados de oricalco" #. ~ Description for {'str': 'lump of orichalcum', 'str_pl': 'lumps of #. orichalcum'} @@ -225018,9 +225475,9 @@ msgstr "" #: data/mods/Magiclysm/items/metals.json msgid "sliver of orichalcum" msgid_plural "slivers of orichalcum" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pedacito de oricalco" +msgstr[1] "pedacitos de oricalco" +msgstr[2] "pedacitos de oricalco" #. ~ Description for {'str': 'sliver of orichalcum', 'str_pl': 'slivers of #. orichalcum'} @@ -225049,9 +225506,9 @@ msgstr "" #: data/mods/Magiclysm/items/metals.json msgid "liquid mercury" msgid_plural "liquid mercury" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "mercurio líquido" +msgstr[1] "mercurio líquido" +msgstr[2] "mercurio líquido" #. ~ Description for {'str_sp': 'liquid mercury'} #: data/mods/Magiclysm/items/metals.json @@ -225063,9 +225520,9 @@ msgstr "" #: data/mods/Magiclysm/items/mutagen.json msgid "concentrated mana serum" msgid_plural "concentrated mana serums" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "suero concentrado de maná" +msgstr[1] "sueros concentrados de maná" +msgstr[2] "sueros concentrados de maná" #. ~ Description for concentrated mana serum #: data/mods/Magiclysm/items/mutagen.json @@ -225109,9 +225566,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "Black Dragons: Swamp Ruins" msgid_plural "copies of Black Dragons: Swamp Ruins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Dragones Negros: Ruinas de Pantano" +msgstr[1] "copias de Dragones Negros: Ruinas de Pantano" +msgstr[2] "copias de Dragones Negros: Ruinas de Pantano" #. ~ Description for {'str': 'Black Dragons: Swamp Ruins', 'str_pl': 'copies #. of Black Dragons: Swamp Ruins'} @@ -225130,9 +225587,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "A Beginner's Guide to Alchemy" msgid_plural "copies of A Beginner's Guide to Alchemy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Principiante en Alquimia" +msgstr[1] "copias de Guía de Principiante en Alquimia" +msgstr[2] "copias de Guía de Principiante en Alquimia" #. ~ Description for {'str': "A Beginner's Guide to Alchemy", 'str_pl': #. "copies of A Beginner's Guide to Alchemy"} @@ -225145,9 +225602,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "A Soulbinder's Guide to Necromancy" msgid_plural "copies of A Soulbinder's Guide to Necromancy" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Guía de Vinculación de Almas en Necromancia" +msgstr[1] "copias de Guía de Vinculación de Almas en Necromancia" +msgstr[2] "copias de Guía de Vinculación de Almas en Necromancia" #. ~ Description for {'str': "A Soulbinder's Guide to Necromancy", 'str_pl': #. "copies of A Soulbinder's Guide to Necromancy"} @@ -225162,9 +225619,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "Magitek Illustrated" msgid_plural "copies of Magitek Illustrated" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Magitek Ilustrado" +msgstr[1] "copias de Magitek Ilustrado" +msgstr[2] "copias de Magitek Ilustrado" #. ~ Description for {'str': 'Magitek Illustrated', 'str_pl': 'copies of #. Magitek Illustrated'} @@ -225183,9 +225640,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "The Weapons of Asgard and Beyond" msgid_plural "copies of The Weapons of Asgard and Beyond" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Armas de Asgard y más" +msgstr[1] "copias de Armas de Asgard y más" +msgstr[2] "copias de Armas de Asgard y más" #. ~ Description for {'str': 'The Weapons of Asgard and Beyond', 'str_pl': #. 'copies of The Weapons of Asgard and Beyond'} @@ -225202,9 +225659,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "Cooking with Poison" msgid_plural "copies of Cooking with Poison" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Cocinando con Veneno" +msgstr[1] "copias de Cocinando con Veneno" +msgstr[2] "copias de Cocinando con Veneno" #. ~ Description for {'str': 'Cooking with Poison', 'str_pl': 'copies of #. Cooking with Poison'} @@ -225219,9 +225676,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "Metals of Legend" msgid_plural "copies of Metals of Legend" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Metales Legendarios" +msgstr[1] "copias de Metales Legendarios" +msgstr[2] "copias de Metales Legendarios" #. ~ Description for {'str': 'Metals of Legend', 'str_pl': 'copies of Metals #. of Legend'} @@ -225238,9 +225695,9 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "Protection from Magical Beasts" msgid_plural "copies of Protection from Magical Beasts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "Protección contra Bestias Mágicas" +msgstr[1] "copias de Protección contra Bestias Mágicas" +msgstr[2] "copias de Protección contra Bestias Mágicas" #. ~ Description for {'str': 'Protection from Magical Beasts', 'str_pl': #. 'copies of Protection from Magical Beasts'} @@ -225254,6 +225711,21 @@ msgstr "" "fuego de un dragón en la tapa. Adentro, tiene muchas maneras de convertir la" " piel y el pellejo de un monstruo en equipo de protección." +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -226338,9 +226810,9 @@ msgstr "" #: data/mods/Magiclysm/items/tools.json msgid "cauldron of purification" msgid_plural "cauldrons of purification" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "caldera de purificación" +msgstr[1] "calderas de purificación" +msgstr[2] "calderas de purificación" #. ~ Description for {'str': 'cauldron of purification', 'str_pl': 'cauldrons #. of purification'} @@ -226458,6 +226930,13 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -226474,13 +226953,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -227633,9 +228105,9 @@ msgstr "" #: data/mods/Magiclysm/vehicles/summoned_vehicles.json msgid "mana core power" msgid_plural "mana core powers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "núcleo de energía de maná" +msgstr[1] "núcleos de energía de maná" +msgstr[2] "núcleos de energía de maná" #. ~ Description for mana core power #: data/mods/Magiclysm/vehicles/summoned_vehicles.json @@ -227780,9 +228252,9 @@ msgstr[2] "torretas antidisturbios rotas" #: data/mods/Modular_Turrets/corpses.json msgid "broken 5.56mm turret" msgid_plural "broken 5.56mm turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta 5.56mm rota" +msgstr[1] "torretas 5.56mm rotas" +msgstr[2] "torretas 5.56mm rotas" #. ~ Description for broken 5.56mm turret #: data/mods/Modular_Turrets/corpses.json @@ -227826,9 +228298,9 @@ msgstr "" #: data/mods/Modular_Turrets/corpses.json msgid "broken 40mm turret" msgid_plural "broken 40mm turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta 40mm rota" +msgstr[1] "torretas 40mm rotas" +msgstr[2] "torretas 40mm rotas" #. ~ Description for broken 40mm turret #: data/mods/Modular_Turrets/corpses.json @@ -227967,9 +228439,9 @@ msgstr "" #: data/mods/Modular_Turrets/corpses.json msgid "broken EMP turret" msgid_plural "broken EMP turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta PEM rota" +msgstr[1] "torretas PEM rotas" +msgstr[2] "torretas PEM rotas" #. ~ Description for broken EMP turret #: data/mods/Modular_Turrets/corpses.json @@ -227983,9 +228455,9 @@ msgstr "" #: data/mods/Modular_Turrets/corpses.json msgid "broken gaurdin gnome" msgid_plural "broken gaurdin gnomes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guardgnomo de jardín roto" +msgstr[1] "guardgnomos de jardín rotos" +msgstr[2] "guardgnomos de jardín rotos" #. ~ Description for broken gaurdin gnome #: data/mods/Modular_Turrets/corpses.json @@ -227995,9 +228467,9 @@ msgstr "Es un gnomo de jardín roto y completamente inofensivo." #: data/mods/Modular_Turrets/corpses.json msgid "broken hack" msgid_plural "broken hacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "hack roto" +msgstr[1] "hacks rotos" +msgstr[2] "hacks rotos" #. ~ Description for broken eyebot #: data/mods/Modular_Turrets/corpses.json @@ -228183,9 +228655,9 @@ msgstr[2] "armas 9mm integrales" #: data/mods/Modular_Turrets/roboguns.json msgid "integral 5.56mm firearm" msgid_plural "integral 5.56mm firearms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arma 5.56mm integral" +msgstr[1] "armas 5.56mm integrales" +msgstr[2] "armas 5.56mm integrales" #: data/mods/Modular_Turrets/items.json #: data/mods/Modular_Turrets/roboguns.json @@ -228206,25 +228678,25 @@ msgstr[2] "escopetas integrales" #: data/mods/Modular_Turrets/roboguns.json msgid "integral beanbag launcher" msgid_plural "integral beanbag launchers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lanzacartuchos no letal integral" +msgstr[1] "lanzacartuchos no letales integrales" +msgstr[2] "lanzacartuchos no letales integrales" #: data/mods/Modular_Turrets/items.json #: data/mods/Modular_Turrets/roboguns.json msgid "integral teargas launcher" msgid_plural "integral teargas launchers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lanzagas lacrimógeno integral" +msgstr[1] "lanzagas lacrimógeno integrales" +msgstr[2] "lanzagas lacrimógeno integrales" #: data/mods/Modular_Turrets/items.json #: data/mods/Modular_Turrets/roboguns.json msgid "integral flamethrower" msgid_plural "integral flamethrowers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "lanzallamas integral" +msgstr[1] "lanzallamas integrales" +msgstr[2] "lanzallamas integrales" #: data/mods/Modular_Turrets/items.json msgid "integral flechette firearm" @@ -228236,16 +228708,16 @@ msgstr[2] "armas de dardos perforantes integrales" #: data/mods/Modular_Turrets/items.json msgid "integral 8x40mm firearm" msgid_plural "integral 8x40mm firearms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arma 8x40mm integral" +msgstr[1] "armas 8x40mm integrales" +msgstr[2] "armas 8x40mm integrales" #: data/mods/Modular_Turrets/items.json msgid "integral 50 caliber firearm" msgid_plural "integral 50 caliber firearms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arma calibre 50 integral" +msgstr[1] "armas calibre 50 integrales" +msgstr[2] "armas calibre 50 integrales" #: data/mods/Modular_Turrets/items.json #: data/mods/Modular_Turrets/roboguns.json @@ -228350,9 +228822,9 @@ msgstr "" #: data/mods/Modular_Turrets/items.json msgid "inactive shotgun defense turret" msgid_plural "inactive shotgun defense turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta defensiva de escopeta inactiva" +msgstr[1] "torretas defensivas de escopeta inactivas" +msgstr[2] "torretas defensivas de escopeta inactivas" #. ~ Description for inactive shotgun defense turret #: data/mods/Modular_Turrets/items.json @@ -228401,9 +228873,9 @@ msgstr "" #: data/mods/Modular_Turrets/items.json msgid "inactive 5.56mm military turret" msgid_plural "inactive 5.56mm military turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta militar 5.56mm inactiva" +msgstr[1] "torretas militares 5.56mm inactivas" +msgstr[2] "torretas militares 5.56mm inactivas" #. ~ Description for inactive 5.56mm military turret #: data/mods/Modular_Turrets/items.json @@ -228522,9 +228994,9 @@ msgstr "" #: data/mods/Modular_Turrets/items.json msgid "inactive military flamethrower turret" msgid_plural "inactive military flamethrower turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta lanzallamas militar inactiva" +msgstr[1] "torretas lanzallamas militares inactivas" +msgstr[2] "torretas lanzallamas militares inactivas" #. ~ Description for inactive military flamethrower turret #: data/mods/Modular_Turrets/items.json @@ -228542,9 +229014,9 @@ msgstr "" #: data/mods/Modular_Turrets/items.json msgid "inactive advanced laser turret" msgid_plural "inactive advanced laser turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta láser avanzada inactiva" +msgstr[1] "torretas láser avanzadas inactivas" +msgstr[2] "torretas láser avanzadas inactivas" #. ~ Description for inactive advanced laser turret #: data/mods/Modular_Turrets/items.json @@ -228610,9 +229082,9 @@ msgstr "" #: data/mods/Modular_Turrets/items.json msgid "inactive advanced EMP turret" msgid_plural "inactive advanced EMP turrets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "torreta avanzada PEM inactiva" +msgstr[1] "torretas avanzadas PEM inactivas" +msgstr[2] "torretas avanzadas PEM inactivas" #. ~ Description for inactive advanced EMP turret #: data/mods/Modular_Turrets/items.json @@ -228652,9 +229124,9 @@ msgstr "" #: data/mods/Modular_Turrets/items.json msgid "gaurdin gnome" msgid_plural "gaurdin gnomes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "guardgnomos de jardín" +msgstr[1] "guardgnomos de jardín" +msgstr[2] "guardgnomos de jardín" #. ~ Description for gaurdin gnome #: data/mods/Modular_Turrets/items.json @@ -229119,9 +229591,9 @@ msgstr[2] "ametralladoras calibre 50 integrales" #: data/mods/Modular_Turrets/roboguns.json msgid "integral needle gun" msgid_plural "integral needle guns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "arma de clavos integral" +msgstr[1] "armas de clavos integrales" +msgstr[2] "armas de clavos integrales" #: data/mods/Modular_Turrets/roboguns.json msgid "integral 8mm firearm" @@ -229176,9 +229648,9 @@ msgstr "" #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json msgid "necco corpse" msgid_plural "necco corpses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "cadáver de necco" +msgstr[1] "cadáveres de necco" +msgstr[2] "cadáveres de necco" #. ~ Description for necco corpse #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json @@ -229293,9 +229765,9 @@ msgstr "" #: data/mods/My_Sweet_Cataclysm/sweet_items.json msgid "SugarKin flyer" msgid_plural "SugarKin flyers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "folleto SugarKin" +msgstr[1] "folletos SugarKin" +msgstr[2] "folletos SugarKin" #. ~ Description for {'str': 'SugarKin flyer'} #: data/mods/My_Sweet_Cataclysm/sweet_items.json @@ -229327,9 +229799,9 @@ msgstr "" #: data/mods/My_Sweet_Cataclysm/sweet_med.json msgid "caramel ointment" msgid_plural "caramel ointments" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" +msgstr[0] "pomada de caramelo" +msgstr[1] "pomadas de caramelo" +msgstr[2] "pomadas de caramelo" #. ~ Description for caramel ointment #: data/mods/My_Sweet_Cataclysm/sweet_med.json @@ -229652,10 +230124,24 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -232160,6 +232646,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -232182,6 +232677,79 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -233701,6 +234269,14 @@ msgstr "Alternar Modo Debug" msgid "Debug Menu" msgstr "Modo Debug" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Ver Mapa de Olor" @@ -234256,6 +234832,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -234414,7 +235010,31 @@ msgstr "Establecer modos de torreta" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -240132,6 +240752,30 @@ msgstr "aábcdeéfghiíjklmnñoópqrstuúüvwxyz" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -245050,6 +245694,10 @@ msgstr "Información..." msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -245166,6 +245814,10 @@ msgstr "Salir a menú principal" msgid "Player…" msgstr "Jugador..." +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -246039,6 +246691,10 @@ msgstr "Ahí no hay un vehículo." msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -258668,6 +259324,11 @@ msgstr "¡Te sacan el/a %s de la mano!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "Intentás darle al/a %s de comer un poco de %s, ¡pero desaparece!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "Querés darle la comida para perros, pero ¡te muerde los dedos!" @@ -264632,6 +265293,11 @@ msgstr "" msgid "Create World" msgstr "Crear Mundo" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "¿Bugs? ¿Sugerencias? Usa los links del MOTD para reportar." @@ -264900,6 +265566,13 @@ msgstr "¿Seguro que quieres borrar %s?" msgid "Sorry, something went wrong." msgstr "Perdón, algo no funcionó." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -268654,6 +269327,15 @@ msgstr[2] "" msgid "Mod version" msgstr "Mod versión" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -271674,13 +272356,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "Enfocar las tendencias hacia:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "humano" -msgstr[1] "humanos" -msgstr[2] "humanos" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -274332,6 +275007,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "General" @@ -275541,6 +276224,16 @@ msgstr "" "Es la cantidad de tiempo que dura la pausa entre los frames de una " "animación, medido en ms." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -275619,64 +276312,77 @@ msgid "Font height" msgstr "Altura de fuente de texto" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" +"Establece la altura de la fuente de texto. Requiere reiniciar el juego." #: src/options.cpp msgid "Font size" msgstr "Tamaño de fuente de texto" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "" +msgid "Set the font size. Requires restart." +msgstr "Establece el tamaño de fuente de texto. Requiere reiniciar el juego." #: src/options.cpp msgid "Map font width" msgstr "Anchura de fuente de texto del mapa" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" +"Establece la anchura de la fuente de texto del mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Map font height" msgstr "Altura de fuente de texto del mapa" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" +"Establece la altura de la fuente de texto del mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Map font size" msgstr "Tamaño de fuente de texto del mapa" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" +"Establece el tamaño de fuente de texto del mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Overmap font width" msgstr "Anchura de fuente de texto sobre el mapa" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" +"Establece la anchura de la fuente de texto sobre el mapa. Requiere reiniciar" +" el juego." #: src/options.cpp msgid "Overmap font height" msgstr "Altura de fuente de texto sobre el mapa" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" +"Establece la altura de la fuente de texto sobre el mapa. Requiere reiniciar " +"el juego." #: src/options.cpp msgid "Overmap font size" msgstr "Tamaño de fuente de texto sobre el mapa" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" +"Establece el tamaño de fuente de texto sobre el mapa. Requiere reiniciar el " +"juego." #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -283486,6 +284192,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "N/D" diff --git a/lang/po/fr.po b/lang/po/fr.po index dec457e2125a..2f52f22f504e 100644 --- a/lang/po/fr.po +++ b/lang/po/fr.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2022 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2022\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: French (https://app.transifex.com/bn-team/teams/113585/fr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1516,10 +1516,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4003,10 +4011,25 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "appendice" @@ -8241,6 +8264,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "Le plafond s'effondre sur vous!" @@ -22799,34 +22833,98 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -22835,30 +22933,86 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -22867,6 +23021,15 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -22875,6 +23038,14 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -22883,18 +23054,56 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "humain" +msgstr[1] "humains" +msgstr[2] "humains" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -49955,11 +50164,9 @@ msgstr[2] "20x66mm flechettes, fait main" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Une cartouche de contrebande qui copie le modèle Rivtech des 20x66mm " -"fléchettes. Étant sans étui on ne peut les désassembler ou les recharger." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -49971,11 +50178,9 @@ msgstr[2] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Une cartouche de contrebande qui copie le modèle Rivtech des 20x66mm " -"chevrotine. Étant sans étui on ne peut les désassembler ou les recharger." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -49988,11 +50193,9 @@ msgstr[2] "cartouches de 20x66mm, fait main" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Une cartouche de contrebande qui copie le modèle Rivtech des 20x66mm balle. " -"Étant sans étui on ne peut les désassembler ou les recharger." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -51804,20 +52007,60 @@ msgstr "" " et cacher les mouvements de troupes." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"Duplication de contrebande de balles 8x40mm sans étui. Étant des balles sans" -" étui, elles ne peuvent pas être désassemblées ou rechargées." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -52235,49 +52478,49 @@ msgstr "" "aucun dégât." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Munition 93mm hautement explosive pour RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "Munition couplée 64mm/105mm hautement explosive pour RPG-7." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "munition thermobarique 105mm pour le RPG-7" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -77196,6 +77439,54 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -78455,6 +78746,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -81192,6 +81484,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "chewing gum" @@ -88261,6 +88554,7 @@ msgstr "Des gaufres aux fruits avec du sirop d'érable." #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -121358,13 +121652,6 @@ msgstr "" "vivre sous terre. Il grouille sous le sol et son nom est dû au fait qu'on le" " rencontre souvent dans les égouts." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -122065,13 +122352,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -132672,7 +132952,8 @@ msgid "I'll kill you if you don't." msgstr "Je vous tue si vous n'obéissez pas." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -140736,10 +141017,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -154084,6 +154361,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -154120,6 +154407,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -184865,6 +185166,14 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -195030,6 +195339,14 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -207813,6 +208130,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -207940,6 +208262,27 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -211907,6 +212250,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -212146,6 +212503,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -212153,6 +212511,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -212216,6 +212575,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -212223,6 +212583,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -212425,6 +212786,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -213372,6 +213747,90 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -214541,6 +215000,21 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -215742,6 +216216,13 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -215758,13 +216239,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -218722,10 +219196,24 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -221173,6 +221661,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -221195,6 +221692,79 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -222621,6 +223191,14 @@ msgstr "Basculer mode déboguage" msgid "Debug Menu" msgstr "Menu déboguage" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Voir la carte du pistage" @@ -223176,6 +223754,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -223334,7 +223932,31 @@ msgstr "Configurer modes de ciblage de la tourelle" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -228994,6 +229616,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -233846,6 +234492,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -233962,6 +234612,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -234831,6 +235485,10 @@ msgstr "Il n'y a pas de véhicule ici." msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -247252,6 +247910,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "Vous essayez de nourrir le chien mais il vous mord les doigts!" @@ -253148,6 +253811,11 @@ msgstr "" msgid "Create World" msgstr "Créer un monde" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -253410,6 +254078,13 @@ msgstr "Êtes-vous sûr de vouloir supprimer %s?" msgid "Sorry, something went wrong." msgstr "Désolé, il y a eu un problème." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -257140,6 +257815,15 @@ msgstr[2] "" msgid "Mod version" msgstr "Version du mod" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -260100,13 +260784,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "humain" -msgstr[1] "humains" -msgstr[2] "humains" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -262737,6 +263414,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Général" @@ -263867,6 +264552,16 @@ msgstr "Vitesse d'animation" msgid "The amount of time to pause between animation frames in ms." msgstr "Temps de pause entre chaque image d'animation en ms." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -263941,7 +264636,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -263949,7 +264644,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -263957,7 +264652,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -263965,7 +264660,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -263973,7 +264668,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -263981,7 +264676,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -263989,7 +264684,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -263997,7 +264692,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -271741,6 +272436,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "aucun" diff --git a/lang/po/hu.po b/lang/po/hu.po index 9e677586fd27..8880b7cfb2f7 100644 --- a/lang/po/hu.po +++ b/lang/po/hu.po @@ -1,13 +1,13 @@ # # Translators: -# Coolthulhu , 2023 # Péter Bodrog, 2023 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Péter Bodrog, 2023\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Hungarian (https://app.transifex.com/bn-team/teams/113585/hu/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1568,10 +1568,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4230,10 +4238,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "vakbeled" @@ -8531,6 +8553,17 @@ msgstr "" msgid "You're winded." msgstr "Kifulladtál." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "Rád szakad a mennyezet!" @@ -23420,34 +23453,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "blob" +msgstr[1] "blob" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -23456,30 +23545,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -23488,6 +23626,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "zombi" +msgstr[1] "zombi" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -23496,6 +23642,13 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -23504,18 +23657,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -50126,12 +50312,9 @@ msgstr[1] "20x66mm nyilacska, kézi öntésű" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"A Rivtech 20x66 mm-es hüvely nélküli páncéltörő nyilacskás lőszerének kézi " -"gyártású kalózmásolata. Mivel hüvely nélküli lőszerről van szó, ezeket sem " -"szétszerelni, sem újratölteni nem lehet." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -50142,12 +50325,9 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"A Rivtech 20x66 mm-es hüvely nélküli lőszerének kézi gyártású kalózmásolata." -" Mivel hüvely nélküli lőszerről van szó, ezeket sem szétszerelni, sem " -"újratölteni nem lehet." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -50159,12 +50339,9 @@ msgstr[1] "20x66mm dumdum golyó, kézi öntésű" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"A Rivtech 20x66 mm-es hüvely nélküli dumdum lőszerének kézi gyártású " -"kalózmásolata. Mivel hüvely nélküli lőszerről van szó, ezeket sem " -"szétszerelni, sem újratölteni nem lehet." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -51890,20 +52067,56 @@ msgstr "" "rakétarendszerhez." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm JHP, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"A Rivtech 8x40mm-es hüvely nélküli lőszer kalózmásolata. Mivel hüvely " -"nélküli lőszerről van szó, ezeket sem szétszerelni, sem újratölteni nem " -"lehet." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -52298,45 +52511,45 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "Doboznyi apró paintball, szinte semmit sem sebez." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "93 mm-es, egylépcsős robbanó muníció az RPG-7-hez." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "64mm/105mm-es, kétlépcsős robbanó muníció az RPG-7-hez." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "105mm-es termobárikus muníció az RPG-7-hez." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -75858,6 +76071,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "Kovászos tojás. Savanyú de finom, és szinte örökké tart." +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -77063,6 +77320,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -79603,6 +79861,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "rágógumi" @@ -86306,6 +86565,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -98634,8 +98894,8 @@ msgstr "" msgctxt "weapon" msgid "pike" msgid_plural "pikes" -msgstr[0] "" -msgstr[1] "" +msgstr[0] "csuka" +msgstr[1] "csuka" #. ~ Description for {'ctxt': 'weapon', 'str': 'pike'} #: data/json/items/melee/spears_and_polearms.json @@ -118828,12 +119088,6 @@ msgstr "" "halványsárgává fakult. A föld alatt rajzik és arról ismeretes, hogy " "kifejezetten a csatornákban él és szaporodik." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "blob" -msgstr[1] "blob" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -119557,12 +119811,6 @@ msgid "" "envelope of scar tissue." msgstr "Eltorzult emberi test, bőre egy nagy darab, kérges hegszövetté vált." -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "zombi" -msgstr[1] "zombi" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -130552,7 +130800,8 @@ msgid "I'll kill you if you don't." msgstr "Mert kinyírlak, ha nem." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "Mindegy." @@ -138693,10 +138942,6 @@ msgstr "" msgid "demon" msgstr "démon" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -152197,6 +152442,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -152233,6 +152488,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -183222,6 +183491,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -193164,6 +193440,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -205206,6 +205489,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -205333,6 +205621,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -209170,6 +209476,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -209375,12 +209693,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -209435,12 +209755,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -209614,6 +209936,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -210502,6 +210836,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -211578,6 +211984,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -212653,6 +213073,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -212668,12 +213094,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -215665,10 +216085,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -218098,6 +218530,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -218120,6 +218561,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -219635,6 +220148,14 @@ msgstr "Debug mód ki/be" msgid "Debug Menu" msgstr "Debug menü" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Szagtérkép megtekintése" @@ -220190,6 +220711,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -220348,7 +220889,31 @@ msgstr "Lövegtornyok célzási módja" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -226043,6 +226608,30 @@ msgstr "abcdefghijklmnopqrstuvwxyz" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -230992,6 +231581,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -231108,6 +231701,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -231974,6 +232571,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -244513,6 +245114,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -250387,6 +250993,11 @@ msgstr "" msgid "Create World" msgstr "Új világ" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -250649,6 +251260,13 @@ msgstr "Biztosan törlöd ezt: %s?" msgid "Sorry, something went wrong." msgstr "Valami nem sikerült." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -254362,6 +254980,15 @@ msgstr[1] "" msgid "Mod version" msgstr "Modverzió" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -257330,12 +257957,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "Fókusz tendencia:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -259974,6 +260595,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Általános" @@ -261155,6 +261784,16 @@ msgstr "Animáció késleltetése" msgid "The amount of time to pause between animation frames in ms." msgstr "Az animációs képkockák közötti idő ms-ban." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -261232,64 +261871,64 @@ msgid "Font height" msgstr "Betű magassága" #: src/options.cpp -msgid "Set the font height. Requires restart." -msgstr "" +msgid "Set the font height. Requires restart." +msgstr "Beállítja a betű magasságát. Újraindítást igényel." #: src/options.cpp msgid "Font size" msgstr "Betűméret" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "" +msgid "Set the font size. Requires restart." +msgstr "Beállítja a betű méretét. Újraindítást igényel." #: src/options.cpp msgid "Map font width" msgstr "Térkép betű szélessége" #: src/options.cpp -msgid "Set the map font width. Requires restart." -msgstr "" +msgid "Set the map font width. Requires restart." +msgstr "Beállítja a térkép betű szélességét. Újraindítást igényel." #: src/options.cpp msgid "Map font height" msgstr "Térkép betű magassága" #: src/options.cpp -msgid "Set the map font height. Requires restart." -msgstr "" +msgid "Set the map font height. Requires restart." +msgstr "Beállítja a térkép betű magasságát. Újraindítást igényel." #: src/options.cpp msgid "Map font size" msgstr "Térkép betűméret" #: src/options.cpp -msgid "Set the map font size. Requires restart." -msgstr "" +msgid "Set the map font size. Requires restart." +msgstr "Beállítja a térkép betű méretét. Újraindítást igényel." #: src/options.cpp msgid "Overmap font width" msgstr "Nagytérkép betű szélessége" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." -msgstr "" +msgid "Set the overmap font width. Requires restart." +msgstr "Beállítja a nagytérkép betű szélességét. Újraindítást igényel." #: src/options.cpp msgid "Overmap font height" msgstr "Nagytérkép betű magassága" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." -msgstr "" +msgid "Set the overmap font height. Requires restart." +msgstr "Beállítja a nagytérkép betű magasságát. Újraindítást igényel." #: src/options.cpp msgid "Overmap font size" msgstr "Nagytérkép betűméret" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." -msgstr "" +msgid "Set the overmap font size. Requires restart." +msgstr "Beállítja a nagytérkép betű méretét. Újraindítást igényel." #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -268998,6 +269637,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "N/A" diff --git a/lang/po/id.po b/lang/po/id.po index 318ef1f231b4..410b730135b1 100644 --- a/lang/po/id.po +++ b/lang/po/id.po @@ -2,7 +2,7 @@ msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Language-Team: Indonesian (https://app.transifex.com/bn-team/teams/113585/id/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1486,10 +1486,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3829,10 +3837,23 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -7971,6 +7992,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21819,34 +21851,82 @@ msgid "seeing this is a bug" msgid_plural "seeing this is a bug" msgstr[0] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21855,30 +21935,72 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21887,6 +22009,13 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -21895,6 +22024,12 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -21903,18 +22038,46 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -46615,8 +46778,8 @@ msgstr[0] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -46627,8 +46790,8 @@ msgstr[0] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -46640,8 +46803,8 @@ msgstr[0] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47991,17 +48154,53 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" msgstr[0] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm JHP, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -48309,41 +48508,41 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -68758,6 +68957,46 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -69752,6 +69991,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -71949,6 +72189,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -77749,6 +77990,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -105725,11 +105967,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -106322,11 +106559,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -116365,7 +116597,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -124169,10 +124402,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -137499,6 +137728,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -137535,6 +137774,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -166757,6 +167010,12 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -176376,6 +176635,12 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -187576,6 +187841,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -187703,6 +187973,21 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -191410,6 +191695,16 @@ msgid "sledge hammer +2" msgid_plural "sledge hammer +2s" msgstr[0] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -191581,11 +191876,13 @@ msgid_plural "cavalry sabre +2s" msgstr[0] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -191631,11 +191928,13 @@ msgid_plural "combat knife +2s" msgstr[0] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -191780,6 +192079,16 @@ msgid "dao +2" msgid_plural "dao +2s" msgstr[0] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -192609,6 +192918,66 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -193592,6 +193961,19 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -194541,6 +194923,11 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -194555,11 +194942,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -197253,10 +197635,20 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -199520,6 +199912,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -199542,6 +199943,77 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -200968,6 +201440,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -201523,6 +202003,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -201681,7 +202181,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -207184,6 +207708,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -211972,6 +212520,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -212088,6 +212640,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -212953,6 +213509,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -225220,6 +225780,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -231066,6 +231631,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -231326,6 +231896,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -235025,6 +235602,15 @@ msgstr[0] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -237981,11 +238567,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -240570,6 +241151,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "" @@ -241642,6 +242231,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -241716,7 +242315,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -241724,7 +242323,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -241732,7 +242331,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -241740,7 +242339,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -241748,7 +242347,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -241756,7 +242355,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -241764,7 +242363,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -241772,7 +242371,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -249304,6 +249903,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/is.po b/lang/po/is.po index 578d211051f2..8a77ba98525a 100644 --- a/lang/po/is.po +++ b/lang/po/is.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2020 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2020\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Icelandic (https://app.transifex.com/bn-team/teams/113585/is/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1490,10 +1490,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3856,10 +3864,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -7998,6 +8020,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21873,34 +21906,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21909,30 +21998,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "sveppur" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "skordýr" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21941,6 +22079,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "uppvakningur" @@ -21949,6 +22095,13 @@ msgstr "uppvakningur" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -21957,18 +22110,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -47549,8 +47735,8 @@ msgstr[1] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47562,8 +47748,8 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47576,8 +47762,8 @@ msgstr[1] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49048,18 +49234,57 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -49395,45 +49620,45 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -71461,6 +71686,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -72537,6 +72806,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -74941,6 +75211,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -81255,6 +81526,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -111267,12 +111539,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -111915,12 +112181,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -122065,7 +122325,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -129869,10 +130130,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -143202,6 +143459,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -143238,6 +143505,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -173005,6 +173286,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -182890,6 +183178,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -194880,6 +195175,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -195007,6 +195307,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -198844,6 +199162,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -199049,12 +199379,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -199109,12 +199441,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -199288,6 +199622,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -200176,6 +200522,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -201250,6 +201668,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -202325,6 +202757,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -202340,12 +202778,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -205171,10 +205603,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -207496,6 +207940,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -207518,6 +207971,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -208944,6 +209469,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -209499,6 +210032,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -209657,7 +210210,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -215199,6 +215776,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -220000,6 +220601,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -220116,6 +220721,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -220982,6 +221591,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -233279,6 +233892,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -239137,6 +239755,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -239397,6 +240020,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -243108,6 +243738,15 @@ msgstr[1] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -246065,12 +246704,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -248666,6 +249299,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Almennt" @@ -249738,6 +250379,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -249812,7 +250463,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -249820,7 +250471,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -249828,7 +250479,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -249836,7 +250487,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -249844,7 +250495,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -249852,7 +250503,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -249860,7 +250511,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -249868,7 +250519,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -257417,6 +258068,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/it_IT.po b/lang/po/it_IT.po index 7b33a3814e05..0b13e6b34309 100644 --- a/lang/po/it_IT.po +++ b/lang/po/it_IT.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2022 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2022\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Italian (Italy) (https://app.transifex.com/bn-team/teams/113585/it_IT/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1514,10 +1514,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3931,10 +3939,25 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "appendice" @@ -8088,6 +8111,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "Il tetto collassa su di te!" @@ -22359,34 +22393,98 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -22395,30 +22493,86 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -22427,6 +22581,15 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -22435,6 +22598,14 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -22443,18 +22614,56 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -49184,11 +49393,9 @@ msgstr[2] "20x66mm flechette, fatte a mano" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Proiettili a flèchette fatti a mano illegali duplicati dei 20x66mm Rivtech " -"caseless.Essendo caseless non possono essere disassemblati o ricaricati." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -49200,11 +49407,9 @@ msgstr[2] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Duplicato fatto a mano ed illegale dei pallettoni caseless della Rivtech da " -"20x66mm. Essendo caseless, non possono essere disassemblati o riutilizzati." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -49217,12 +49422,9 @@ msgstr[2] "20x66mm pallettone, fatti a mano" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Duplicati clandestini dei proiettili Rivtech 20x66mm senza bossolo. Essendo " -"proiettili senza bossolo, questi non possono essere disassemblati o " -"riutilizzati." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -51089,20 +51291,60 @@ msgstr "" "movimenti delle truppe." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm JHP, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"Duplicato pirata dei proiettili 8x40mm senza capsula. Essendo proiettili " -"senza capsula, questi non possono essere disassemblati o ricaricati." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -51528,49 +51770,49 @@ msgstr "" "allo zero." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Munizione 93mm HE altamente esplosiva a stage singolo per RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "Razzo da 64mm/105mm a doppia detonazione per RPG-7. " #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "Razzo da 105mm ad esplosione termobarica per RPG-7." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -75865,6 +76107,54 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -77104,6 +77394,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -79749,6 +80040,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -86663,6 +86955,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -118991,13 +119284,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -119680,13 +119966,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -129983,7 +130262,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -137792,10 +138072,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -151135,6 +151411,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -151171,6 +151457,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -181650,6 +181950,14 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -191816,6 +192124,14 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -204600,6 +204916,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -204727,6 +205048,27 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -208697,6 +209039,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -208936,6 +209292,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -208943,6 +209300,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -209006,6 +209364,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -209013,6 +209372,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -209215,6 +209575,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -210162,6 +210536,90 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -211332,6 +211790,21 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -212533,6 +213006,13 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -212549,13 +213029,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -215513,10 +215986,24 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -217915,6 +218402,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -217937,6 +218433,79 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -219363,6 +219932,14 @@ msgstr "" msgid "Debug Menu" msgstr "Menu di debug" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Visualizza la mappa dell'odore" @@ -219918,6 +220495,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -220076,7 +220673,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -225677,6 +226298,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -230508,6 +231153,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -230624,6 +231273,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -231491,6 +232144,10 @@ msgstr "Non ci sono veicoli in quella direzione." msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -243838,6 +244495,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -249711,6 +250373,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -249971,6 +250638,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -253694,6 +254368,15 @@ msgstr[2] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -256652,13 +257335,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -259280,6 +259956,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Generali" @@ -260391,6 +261075,16 @@ msgstr "Ritardo animazioni" msgid "The amount of time to pause between animation frames in ms." msgstr "Tempo in millisecondi che trascorre tra un'animazione e l'altra." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -260465,7 +261159,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -260473,7 +261167,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -260481,7 +261175,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -260489,7 +261183,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -260497,7 +261191,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -260505,7 +261199,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -260513,7 +261207,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -260521,7 +261215,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -268110,6 +268804,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "Nessuna" diff --git a/lang/po/ja.po b/lang/po/ja.po index 6e97ded95edd..5e2a6067e436 100644 --- a/lang/po/ja.po +++ b/lang/po/ja.po @@ -1,14 +1,14 @@ # # Translators: -# くりやまたいせい, 2022 -# O M, 2022 +# くりやまたいせい, 2023 +# O M, 2023 # Coolthulhu , 2023 # Pigmentblue15, 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Pigmentblue15, 2023\n" "Language-Team: Japanese (https://app.transifex.com/bn-team/teams/113585/ja/)\n" "MIME-Version: 1.0\n" @@ -1670,10 +1670,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4078,10 +4086,23 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "追加部位" @@ -8230,6 +8251,17 @@ msgstr "呼吸ができません...喘息の発作です!" msgid "You're winded." msgstr "息切れしています。" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "天井が崩れてきました!" @@ -22655,34 +22687,82 @@ msgid "seeing this is a bug" msgid_plural "seeing this is a bug" msgstr[0] "このアイテムが見えている場合はバグが発生しています" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "哺乳類" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "両生類" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "鳥類" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "爬虫類" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "魚類" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "変異体" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "異界生物" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "ブロブ" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "ブロブ" @@ -22691,30 +22771,72 @@ msgstr "ブロブ" msgid "plop." msgstr "ペタッ。" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "真菌" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "異界植物" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "虫" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "クモ類" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "植物" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "軟体動物" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "ワーム" @@ -22723,6 +22845,13 @@ msgstr "ワーム" msgid "rustle." msgstr "ガサッ。" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "ゾンビ" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "ゾンビ" @@ -22731,6 +22860,12 @@ msgstr "ゾンビ" msgid "shuffling." msgstr "[何かを引きずるような音]" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "ロボット" @@ -22739,18 +22874,46 @@ msgstr "ロボット" msgid "mechanical whirring." msgstr "[唸るような機械音]" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "怪物" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "異形" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "人間" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "人間" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -47744,9 +47907,9 @@ msgstr[0] "弾薬(20x66mm/手製矢弾)" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "矢弾仕様のRivtech社製20x66mmケースレス弾を非公式に手作りしたものです。ケースレスの弾薬は分解、再利用ができません。" +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "" #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -47756,9 +47919,9 @@ msgstr[0] "弾薬(20x66mm/手製散弾)" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "散弾仕様のRivtech社製20x66mmケースレス弾を非公式に手作りしたものです。ケースレスの弾薬は分解、再利用ができません。" +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "" #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -47769,9 +47932,9 @@ msgstr[0] "弾薬(20x66mm/手製単発弾)" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "単発弾仕様のRivtech社製20x66mmケースレス弾を非公式に手作りしたものです。ケースレスの弾薬は分解、再利用ができません。" +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." +msgstr "" #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -49174,16 +49337,52 @@ msgid "" msgstr "カールグスタフM3無反動砲用の84x246mm煙幕弾です。一般的には合図や標的の指示、そして部隊移動の援護に使用します。" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" -msgstr[0] "弾薬(8x40mm/JHP/非正規)" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." -msgstr "Rivtech社製8x40mmケースレス弾の非正規コピー品です。ケースレスの弾薬は分解、再利用ができません。" +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -49496,41 +49695,41 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "小型のペイントボールです。この玉はほとんどダメージを与えられません。" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" -msgstr[0] "弾頭(PG-7VL 93mm)" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" +msgstr[0] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "RPG-7用の93mm単段式榴弾です。" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" -msgstr[0] "弾頭(PG-7VR 64mm/105mm)" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" +msgstr[0] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "RPG-7用の64mm/105mmタンデム式榴弾です。" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" -msgstr[0] "弾頭(TBG-7V 105mm)" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" +msgstr[0] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "RPG-7用の105mm燃料気化榴弾です。" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" -msgstr[0] "弾頭(OG-7V 40mm)" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" +msgstr[0] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -70177,6 +70376,46 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "卵の酢漬けです。少々塩辛いですが美味しく食べられ、長持ちします。" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -71173,6 +71412,7 @@ msgstr "甘みがある乾燥したクラッカーです。そのまま食べる #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "クッキー" @@ -73384,6 +73624,7 @@ msgstr "滅菌処理済の生理食塩水が原料の点眼薬です。ドライ #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "チューインガム" @@ -79282,6 +79523,7 @@ msgstr "本物のメープルシロップを使用した、カリカリで美味 #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "クラッカー" @@ -107885,11 +108127,6 @@ msgid "" "of infesting sewer lines." msgstr "地下生活を続けるうちに淡黄色に変色した、メクラヘビの変異体の一種です。地下に群れで生活し、下水道を住処にしています。" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "ブロブ" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -108495,11 +108732,6 @@ msgid "" "envelope of scar tissue." msgstr "歪んだ人間の皮膚が分厚く変化し、傷跡が硬く覆われています。" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "ゾンビ" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -118772,7 +119004,8 @@ msgid "I'll kill you if you don't." msgstr "言う通りにしなければ殺す。" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "なんでもない。" @@ -126716,10 +126949,6 @@ msgstr "化け物" msgid "demon" msgstr "悪魔" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "怪物" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "名状しがたい獣" @@ -140528,6 +140757,16 @@ msgid "" "coming no further. Go away." msgstr "動くな。どうやってここに入ったのか知らないが、それ以上近づくな。帰ってくれ。" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "待って!何だって??" @@ -140564,6 +140803,20 @@ msgstr "その、防護装備っていうのは?" msgid "Alright, I'm leaving." msgstr "わかった、もう行くよ。" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "嫌だ。さっさと出て行け。" @@ -170696,6 +170949,12 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "浮遊するヒーターに改造した監視ロボットです。暖気を噴出し続けて密閉された空間を暖めます。" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "大変動以前に人の手で創造された知性生物です。" @@ -180444,6 +180703,12 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "恐竜" @@ -191822,6 +192087,11 @@ msgstr "ポーション" msgid "RUNES" msgstr "ルーン" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "マナ集中" @@ -191957,6 +192227,21 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "魔法使いの隠れ家" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "魔法使いの秘匿研究室" @@ -195702,6 +195987,16 @@ msgid "sledge hammer +2" msgid_plural "sledge hammer +2s" msgstr[0] "スレッジハンマー+2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -195873,11 +196168,13 @@ msgid_plural "cavalry sabre +2s" msgstr[0] "騎兵刀+2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "バール+1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "バール+2" @@ -195923,11 +196220,13 @@ msgid_plural "combat knife +2s" msgstr[0] "コンバットナイフ+2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "狩猟用ナイフ+1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "狩猟用ナイフ+2" @@ -196072,6 +196371,16 @@ msgid "dao +2" msgid_plural "dao +2s" msgstr[0] "中国刀+2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -196905,6 +197214,66 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "裏面に刻まれた呪文を読み上げると表面に描かれた物に変化する、大きな銀貨です。この硬貨にはバールが描かれています。" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -197898,6 +198267,19 @@ msgid "" msgstr "" "ドラゴンの吐く炎を押しとどめる盾の絵が表紙に書かれた、革装丁の本です。モンスターの皮革を加工して身体を保護する防具を作る様々な方法が掲載されています。" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -198854,6 +199236,11 @@ msgid "" "much more expensive." msgstr "オリハルコン製のフレームです。鋼鉄よりもはるかに頑丈ですが、価格も桁違いです。" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "デーモンスパイダー" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -198869,11 +199256,6 @@ msgid "" msgstr "" "既に小型犬ほどのサイズですが、これでも非常に若いデーモンスパイダーです。全身が赤いためデーモンと呼ばれています。こんな化け物を大変動以前には見た事がありません。非常に素早く動き、大きな牙からは毒が滴っています。" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "デーモンスパイダー" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -201660,10 +202042,20 @@ msgid "" msgstr "" "キャンディーか何かのチラシです。恐ろしげにこちらを見つめる、滑らかな飴で作られた人間が描かれています。「シュガーキン(砂糖の血族)は史上初の等身大ヒューマンキャンディーです!君は真のモンスターか?これを食べ尽くすことが出来るか?」" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "フカッ。" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "ポフッ。" @@ -203969,6 +204361,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "田舎で遊びましょう。農場、森林、村以外の構造物が生成されません。推奨される街のサイズは1、街の間隔は8です。" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "追加 - 目視アイコン(HitButton_iso)" @@ -203991,6 +204392,77 @@ msgid "" "retrodays tileset." msgstr "モンスターがプレイヤーを目視した際に態度を示すアイコンを表示します。retrodays tileset用のデザインです。" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "変更 - 器用と連動した速度" @@ -205417,6 +205889,14 @@ msgstr "切替/デバッグモード" msgid "Debug Menu" msgstr "デバッグメニュー" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "匂いマップ" @@ -205972,6 +206452,26 @@ msgstr "日記を.txtに出力" msgid "Add new page" msgstr "新規ページ追加" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -206130,7 +206630,31 @@ msgstr "設定/タレット照準モード" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -211706,6 +212230,30 @@ msgstr "アイウエオカキクケコサシスセソタチツテトナニヌネ msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -216573,6 +217121,10 @@ msgstr "情報..." msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "車両..." @@ -216689,6 +217241,10 @@ msgstr "ゲーム終了" msgid "Player…" msgstr "プレイヤー..." +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -217558,6 +218114,10 @@ msgstr "そこには車両が存在しません。" msgid "By how much? (in kJ, negative to discharge)" msgstr "バッテリー残量を設定(単位:kJ、マイナスで減少)" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -230186,6 +230746,11 @@ msgstr "%sは差し出されたものを叩き落としました!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "%sに%sを与えようとすると、消えてしまいました!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "ドッグフードを与えようとしましたが、指を噛まれました!" @@ -236060,6 +236625,11 @@ msgstr "" msgid "Create World" msgstr "世界生成" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "バグを見つけた?提案を思いついた?MOTD内のリンクを利用して報告してください。" @@ -236320,6 +236890,13 @@ msgstr "%sを削除しますか?" msgid "Sorry, something went wrong." msgstr "申し訳ありません、何らかの問題が発生しています。" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -240151,6 +240728,15 @@ msgstr[0] "" msgid "Mod version" msgstr "MODバージョン" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -243113,11 +243699,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "変動:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "人間" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -245753,6 +246334,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "全般" @@ -246849,6 +247438,16 @@ msgstr "アニメーション/遅延" msgid "The amount of time to pause between animation frames in ms." msgstr "アニメーションのフレーム間の遅延を設定します。単位はミリ秒です。" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -246925,64 +247524,64 @@ msgid "Font height" msgstr "フォント/縦幅" #: src/options.cpp -msgid "Set the font height. Requires restart." -msgstr "" +msgid "Set the font height. Requires restart." +msgstr "フォントの縦幅を設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Font size" msgstr "フォント/サイズ" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "" +msgid "Set the font size. Requires restart." +msgstr "フォントのサイズを設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Map font width" msgstr "マップフォント/横幅" #: src/options.cpp -msgid "Set the map font width. Requires restart." -msgstr "" +msgid "Set the map font width. Requires restart." +msgstr "マップフォントの横幅を設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Map font height" msgstr "マップフォント/縦幅" #: src/options.cpp -msgid "Set the map font height. Requires restart." -msgstr "" +msgid "Set the map font height. Requires restart." +msgstr "マップフォントの縦幅を設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Map font size" msgstr "マップフォント/サイズ" #: src/options.cpp -msgid "Set the map font size. Requires restart." -msgstr "" +msgid "Set the map font size. Requires restart." +msgstr "マップフォントのサイズを設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Overmap font width" msgstr "全体マップフォント/横幅" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." -msgstr "" +msgid "Set the overmap font width. Requires restart." +msgstr "全体マップフォントの横幅を設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Overmap font height" msgstr "全体マップフォント/縦幅" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." -msgstr "" +msgid "Set the overmap font height. Requires restart." +msgstr "全体マップフォントの縦幅を設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Overmap font size" msgstr "全体マップフォント/サイズ" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." -msgstr "" +msgid "Set the overmap font size. Requires restart." +msgstr "全体マップフォントのサイズを設定します。反映には再起動が必要です。" #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -254577,6 +255176,11 @@ msgstr "欠損しているMOD" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "なし" diff --git a/lang/po/ko.po b/lang/po/ko.po index eb6984d771c8..62db75c085e4 100644 --- a/lang/po/ko.po +++ b/lang/po/ko.po @@ -1,37 +1,37 @@ # # Translators: -# K.H L. , 2021 -# 성취감 , 2021 -# 구름베개 , 2021 -# Sungho Han , 2021 -# dump dump , 2021 -# 이현우, 2021 -# jh bae, 2021 -# Sail Recycle , 2021 -# 이찬기, 2021 -# k jh <4492kjh@gmail.com>, 2022 -# ---, 2022 -# Zine Bos, 2022 -# Cokafold, 2022 -# 김정국 , 2022 -# hi mate, 2022 -# 99ecc9bedd126001a124273d35cfc4be_27e32b0 , 2022 -# kamo - , 2022 -# 백도 , 2022 -# 모랑랑, 2022 -# JJ J , 2022 # hy gx, 2022 -# Coolthulhu , 2023 +# 구름베개 , 2023 +# hi mate, 2023 +# jh bae, 2023 +# ---, 2023 +# 성취감 , 2023 +# K.H L. , 2023 +# dump dump , 2023 +# 이현우, 2023 +# Cokafold, 2023 +# 99ecc9bedd126001a124273d35cfc4be_27e32b0 , 2023 # DelFe, 2023 -# scarf , 2023 # David Kim, 2023 +# Sungho Han , 2023 +# Sail Recycle , 2023 +# k jh <4492kjh@gmail.com>, 2023 +# kamo - , 2023 +# 김정국 , 2023 +# JJ J , 2023 +# Zine Bos, 2023 +# 백도 , 2023 +# scarf , 2023 +# 이찬기, 2023 +# 모랑랑, 2023 +# Coolthulhu , 2023 # Fruitybite, 2023 # 김동현, 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-06 00:16+0000\n" "Last-Translator: 김동현, 2023\n" "Language-Team: Korean (https://app.transifex.com/bn-team/teams/113585/ko/)\n" "MIME-Version: 1.0\n" @@ -1917,10 +1917,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "[전투] 한 마리 잡았고, 앞으로 몇 억 마리..." +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "[전투] 장의사" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "[전투] 무례한 기상" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "[전투] 평화주의자" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "[전투] 학살자" @@ -4433,12 +4441,27 @@ msgstr "영구 발전기" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" "디버그늄을 동력원으로 사용하는 영구 발전기가 설치되었습니다. 활성화시키면 전력 생산량이 두배가 됩니다. 이걸 보고 있다면 디버그 중이어야" " 할겁니다." +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "디버그 연료 전지 시스템" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" +"태양의 힘을 내 손 안에! 디버그늄을 동력원으로 사용하는 영구 발전기가 설치되었습니다. 활성화시키면 전력 생산량이 두배가 됩니다. 이걸 " +"보고 있다면 디버그 중이어야 할겁니다." + #: data/json/body_parts.json msgid "appendix" msgstr "기타부위" @@ -8594,6 +8617,17 @@ msgstr "숨이 쉬어지지 않습니다… 천식 발작입니다!" msgid "You're winded." msgstr "호흡이 힘듭니다." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "기관지 경련" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "공기 중의 무언가 탓에 숨쉬기 어렵고, 천식을 자극합니다. 천식 발작이 발생할 확률이 증가합니다." + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "머리 위의 천장이 무너집니다!" @@ -23626,34 +23660,82 @@ msgid "seeing this is a bug" msgid_plural "seeing this is a bug" msgstr[0] "이걸 보고 있다면 버그입니다." +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "포유류" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "포유류" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "양서류" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "양서류" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "조류" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "조류" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "파충류" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "파충류" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "어류" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "어류" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "돌연변이" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "돌연변이" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "지옥 생물" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "지옥 생물" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "블럽" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "블럽" @@ -23662,30 +23744,72 @@ msgstr "블럽" msgid "plop." msgstr "퐁당" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "진균" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "진균체" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "거머리 식물" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "거머리 식물" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "곤충" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "곤충" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "거미" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "절지류" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "식물" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "식물" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "연체동물" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "연체동물" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "벌레" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "벌레" @@ -23694,6 +23818,13 @@ msgstr "벌레" msgid "rustle." msgstr "살랑이는 소리" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "좀비" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "좀비" @@ -23702,6 +23833,12 @@ msgstr "좀비" msgid "shuffling." msgstr "질질 끌리는 소리" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "로봇" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "로봇" @@ -23710,18 +23847,46 @@ msgstr "로봇" msgid "mechanical whirring." msgstr "기계가 돌아가는 소리" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "공포" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "공포" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "변이체" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "이형체" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "환각" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "인간" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "인간" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "정체불명" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -29285,7 +29450,7 @@ msgstr "냉동고를 켰습니다." #: data/mods/Aftershock/vehicles/vehicle_parts.json msgid "freezer" msgid_plural "freezers" -msgstr[0] "냉동고" +msgstr[0] "냉장고" #. ~ Description for freezer #. ~ Description for minifreezer @@ -49309,10 +49474,9 @@ msgstr[0] "20x66mm 플레셰트탄, 수제" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "" -"리브텍 플레쉐트형 20x66mm 무탄피 산탄을 불법으로 모방해서 만든 수제 탄약. 무탄피탄이므로 분해나 재사용이 불가능합니다." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "리브텍 20x66mm 무탄피 플레셰트 산탄의 수제 복제품입니다. 탄피가 없어 분해나 재사용할 수 없습니다." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -49322,9 +49486,9 @@ msgstr[0] "20x66mm 산탄, 수제" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "리브텍 벅샷형 20x66mm 무탄피 산탄을 불법으로 모방해서 만든 수제 탄약. 무탄피탄이므로 분해나 재사용이 불가능합니다." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "리브텍 20x66mm 무탄피 벅샷 산탄의 수제 복제품입니다. 탄피가 없어 분해나 재사용할 수 없습니다." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -49335,11 +49499,9 @@ msgstr[0] "20x66mm 슬러그탄, 수제" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "" -"커다란 고형 발사체를 사용한 리브텍 슬러그형 20x66mm 무탄피 산탄을 불법으로 모방해서 만든 수제 탄약. 무탄피탄이므로 분해나 " -"재사용이 불가능합니다." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." +msgstr "리브텍 20x66mm 무탄피 슬러그 산탄의 수제 복제품입니다. 탄피가 없어 분해나 재사용할 수 없습니다." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -50810,16 +50972,52 @@ msgid "" msgstr "칼 구스타프 M3 무반동포에 사용되는 84x246mm 연막탄. 일반적으로 신호, 목표 지정, 병력 이동 은폐에 사용됩니다." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" -msgstr[0] "수제 8x40mm JHP" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "수제 8x40mm JHP탄" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "리브텍 8x40mm 무탄피 JHP탄의 수제 복제품입니다. 탄피가 없어 분해나 재사용할 수 없습니다." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "수제 8x40mm 무탄피탄" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." -msgstr "리브텍 8x40mm 무탄피탄을 불법으로 모방해서 만든 수제 탄약. 무탄피탄이므로 분해나 재사용이 불가능합니다." +msgstr "리브텍 8x40mm 무탄피탄의 수제 복제품입니다. 탄피가 없어 분해나 재사용할 수 없습니다." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "수제 8x40mm 고속철갑탄" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "리브텍 8x40mm 무탄피 고속철갑탄의 수제 복제품입니다. 탄피가 없어 분해나 재사용할 수 없습니다." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "수제 8x40mm 예광탄" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "리브텍 8x40mm 무탄피 예광탄의 수제 복제품입니다. 탄피가 없어 분해나 재사용할 수 없습니다." #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -51141,41 +51339,41 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "작은 페인트볼들로 채워진 튜브. 탄환으로 사용해도 피해를 거의 주지 못합니다. " #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" -msgstr[0] "PG-7VL 93mm 로켓" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" +msgstr[0] "PG-7VL RPG-7 통상 로켓" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "RPG-7에 사용하는 93mm 구경 1단구성 고폭탄입니다." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" -msgstr[0] "PG-7VR 64mm/105mm 로켓" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" +msgstr[0] "PG-7VR RPG-7 탠덤 로켓" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "RPG-7용 64mm/105mm 고폭 탄뎀 로켓." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" -msgstr[0] "TBG-7V 105mm 로켓" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" +msgstr[0] "TBG-7V RPG-7 열압력 로켓" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "RPG-7용 105mm 초고열 로켓탄." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" -msgstr[0] "OG-7V 40mm 로켓" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" +msgstr[0] "OG-7V RPG-7 파편 로켓" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -72325,6 +72523,46 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "절인 계란. 상당히 짜지만, 꽤 맛있고 오랫동안 상하지 않는다." +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "서양우엉 오믈렛" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "서양우엉 오믈렛입니다." + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "산나물 오믈렛" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "산나물 오믈렛입니다." + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "버섯 오믈렛" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "버섯 오믈렛입니다." + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "스페인식 오믈렛" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "스페인식 오믈렛입니다." + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -73329,6 +73567,7 @@ msgstr "건조하고 달콤한 이 크래커는 갈증을 유발하지만, 초 #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "쿠키" @@ -75594,6 +75833,7 @@ msgstr "염분을 함유 하고있는 살균된 안약. 안구 건조증을 치 #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "껌" @@ -81520,6 +81760,7 @@ msgstr "진짜 메이플 시럽을 곁들인 바삭바삭하고 맛있는 와플 #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "크래커" @@ -87855,7 +88096,7 @@ msgstr[0] "V29 레이져 권총" msgid "" "This V29 laser pistol was one of the first handheld laser weapons. It is " "larger than most traditional handguns, but displays no recoil whatsoever." -msgstr "" +msgstr "첫 도수 레이저 무기인 V29 레이저 권총입니다. 대부분의 전통적인 권총보다 크지만, 아무 반동도 발생하지 않습니다." #: data/json/items/gunmod/accessories.json msgid "arrow rest" @@ -110947,11 +111188,6 @@ msgid "" "of infesting sewer lines." msgstr "호전적인 변종 지렁이뱀으로, 지하에서의 오랜 삶 때문에 창백한 노란색 피부를 가지고 있습니다." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "블럽" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -111590,11 +111826,6 @@ msgid "" "envelope of scar tissue." msgstr "변형된 인간의 몸. 피부는 흉터 조직의 두껍고 굳은 껍질같이 변형되었습니다." -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "좀비" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -122194,7 +122425,8 @@ msgid "I'll kill you if you don't." msgstr "아니면 죽여버리겠어." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "신경쓰지마." @@ -126044,7 +126276,7 @@ msgstr "정말 고마워, 우리 둘다 살 수 있을지도 모르겠네." #: data/json/npcs/missiondef.json msgid "Ya, it was a long shot I admit." -msgstr "그래, 정말 멀리도 쐈더군. 인정하지." +msgstr "그래, 뭐. 그럴 가능성이 희박한건 인정하지." #: data/json/npcs/missiondef.json msgid "I'm not sure, maybe a news station would have what we are looking for?" @@ -130366,10 +130598,6 @@ msgstr "괴물" msgid "demon" msgstr "악마" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "공포체" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "형용할 수 없는 괴물" @@ -136720,7 +136948,7 @@ msgstr "" #: data/json/npcs/necropolis/NPC_Old_Guard_Captain.json msgid "Locate Commo Team" -msgstr "" +msgstr "통신 팀 확보" #: data/json/npcs/necropolis/NPC_Old_Guard_Captain.json #: data/json/npcs/necropolis/NPC_Old_Guard_Commo.json @@ -144326,7 +144554,7 @@ msgstr "" #: data/json/npcs/refugee_center/surface_visitors/NPC_old_guard_representative.json msgid "What do you have for me?" -msgstr "" +msgstr "뭔가 필요한게 있나?" #: data/json/npcs/refugee_center/surface_visitors/NPC_old_guard_representative.json msgid "" @@ -144684,6 +144912,16 @@ msgid "" "coming no further. Go away." msgstr "멈춰. 네가 어떻게 이 곳에 들어왔는지는 모르지만, 더 이상 접근하지마. 돌아가." +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "잠깐! 뭐라고??" @@ -144720,6 +144958,20 @@ msgstr "네가 말했던 보호 장비 말인데?" msgid "Alright, I'm leaving." msgstr "알겠어, 떠나지." +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "[인터콤이 시키는 대로 한다]" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "하드드라이브를 지금은 안 가져왔는데. 다시 가지고 올게." + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "아니. 이제 떠나." @@ -157461,7 +157713,7 @@ msgstr "" #: data/json/recipes/basecamps/recipe_primitive_field.json msgid "Farm basic shed" -msgstr "" +msgstr "농장 기초 헛간" #: data/json/recipes/basecamps/recipe_primitive_field.json msgid "" @@ -166607,6 +166859,9 @@ msgid "" "nuclear attack. Until and unless such an event occurs, our growing planned " "community topside will provide regular exchange of personnel and materiel." msgstr "" +"깨끗하고 효율적으로! 본 시설이 완성되면 무슨 일이 일어나더라도 자기유지가 가능해질 것입니다. 3층에 위치한 새 반응로 시설이 설령 " +"핵공격으로 인한 EMP가 발생하더라도 끊기지 않고 지속적으로 전력을 공급할 것입니다. 그런 일이 일어날 때까지는, 그리고 설령 " +"일어나더라도 발전 계획에 따른 지상 공동체가 정기적으로 인원 및 물자를 공급할 것입니다." #: data/json/snippets/snippets.json msgid "" @@ -175328,6 +175583,12 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "부유형 차량용 히터로 개조된 아이봇입니다. 밀폐된 공간의 난방을 위해 지속적으로 따뜻한 공기를 내뿜습니다." +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "대재앙 이전에 인류에 의해 창조된, 지성을 가진 동물입니다." @@ -179645,7 +179906,7 @@ msgstr[0] "C.R.I.T. 라인 건" msgid "" "Experimental high power cutting tool under development in C.R.I.T. R&D. It " "fires plasma in a wide line for slicing into dense materials." -msgstr "" +msgstr "C.R.I.T. R&D 부서에서 개발 중이던 실험적 절단기구입니다. 고밀도 물질을 절단할 수 있는 플라즈마 선을 분출합니다." #: data/mods/CRT_EXPANSION/items/crt_gun.json msgid "C.R.I.T. Pulse Rifle" @@ -179747,6 +180008,9 @@ msgid "" " allow for enhanced oxygen intake and safety even under bombardment. It has" " an integrated HUD and the option to turn it on for more features." msgstr "" +"C.R.I.T. 특수부대용 가스마스크입니다. 최신 전자기기가 장착되었고 케블라를 덧대 착용자의 머리가 온전하도록 보호합니다. 다양한 " +"필터와 기타 최첨단 장비를 통해 설령 폭격을 맞는 중이라도 원활하게 산소를 공급하고 유독물질을 차단해줍니다. 내장된 HUD를 작동시켜 더" +" 많은 기능을 활성화할 수 있습니다." #: data/mods/CRT_EXPANSION/items/crt_toolarmor.json msgid "C.R.I.T. gasmask (on)" @@ -179767,6 +180031,8 @@ msgid "" "draining power for the HUD, low-level nightvision and other protective " "elements." msgstr "" +"C.R.I.T. 특수부대용 가스마스크입니다. 현재 작동 중이며, HUD, 저수준 야간시야, 환경 보호를 위해 지속적으로 전력을 " +"소모합니다." #: data/mods/CRT_EXPANSION/items/crt_toolarmor.json msgid "C.R.I.T. EM vest (off)" @@ -179795,6 +180061,9 @@ msgid "" "Spec Ops for its ease of use and manuverability. Turn it on for suit mode, " "extra protection and movement." msgstr "" +"C.R.I.T. 특수부대용 이동보조 조끼입니다. 최첨단 필라멘트와 서보 모터를 통해 착용자를 보호하는 동시에 이동을 보조하지만, 전력을 " +"상당히 소모합니다. C.R.I.T. 특수부대가 높은 활용성과 기동성에 주목해 흔히 착용합니다. 작동시키면 수트 모드가 활성화되어 방어력과" +" 이동력을 향상시킵니다." #: data/mods/CRT_EXPANSION/items/crt_toolarmor.json msgid "C.R.I.T. EM vest (on)" @@ -185422,6 +185691,12 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "공룡연구소 수술실 접근 제어판" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "공룡" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "공룡" @@ -187943,7 +188218,7 @@ msgstr[0] "녹색과 노란색의 사족보행 어린 공룡" #: data/mods/DinoMod/monsters/juvenile.json msgid "gray and magenta two-legged juvenile" msgid_plural "gray and magenta two-legged juveniles" -msgstr[0] "회색과 자홍색의 이족보행 어린 공룡" +msgstr[0] "" #. ~ Description for gray and magenta two-legged juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -190689,7 +190964,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Crashing Chasm" msgid_plural "Five Horn Death Punches" -msgstr[0] "파이브 혼 데스 펀치" +msgstr[0] "다섯 뿔 달린 죽음" #. ~ Description for {'str': 'Crashing Chasm', 'str_pl': 'Five Horn Death #. Punches'} @@ -190703,7 +190978,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Five Horn Death Punch" msgid_plural "Five Horn Death Punches" -msgstr[0] "파이브 혼 데스 펀치" +msgstr[0] "다섯 뿔 달린 죽음" #. ~ Description for {'str': 'Five Horn Death Punch', 'str_pl': 'Five Horn #. Death Punches'} @@ -195193,6 +195468,9 @@ msgid "" "controllable in automatic fire. It feeds from detachable box magazines, " "which are easy to unload into close range targets." msgstr "" +"권총탄을 연사하도록 만들어진 작은 장총으로, 참호전, 차량 운전수, SWAT 팀과 특수부대에게 완벽하게 유용합니다. 제대로 된 소총만큼 " +"정확하지는 않고 특히 장거리에서 이 단점이 크게 드러나지만, 자동사격시 반동을 제어하기가 쉽습니다. 교체 가능한 박스 탄창을 이용하는 " +"덕분에 근거리 목표에게 탄을 쏴갈기기 편리합니다." #: data/mods/Generic_Guns/firearms/pistol.json msgid "9mm pipe gun" @@ -195299,6 +195577,8 @@ msgid "" "unsuited for taking on anything but small game, as it is meant to poke holes" " in paper. Accepts box magazines." msgstr "" +"저렴하고 흔한 연습탄을 발사하는 소형 권총으로, 훈련 및 표적 사격용으로 아주 흔하게 쓰입니다. 작은 사냥감이나 표적지 이외의 것을 " +"노리기에는 부적절합니다. 박스 탄창을 사용합니다." #: data/mods/Generic_Guns/firearms/pistol_tiny.json msgid ".22 revolver" @@ -195312,6 +195592,8 @@ msgid "" "unsuited for taking on anything but small game, as it is meant to poke holes" " in paper. Can hold 8 bullets." msgstr "" +"저렴하고 흔한 연습탄을 발사하는 소형 리볼버로, 훈련 및 표적 사격용으로 아주 흔하게 쓰입니다. 작은 사냥감이나 표적지 이외의 것을 " +"노리기에는 부적절합니다. 탄약을 8발 장전할 수 있습니다." #: data/mods/Generic_Guns/firearms/pistol_tiny.json msgid ".22 pipe gun" @@ -196153,14 +196435,14 @@ msgstr "진균체의 기하급수적인 성장능력을 크게 제한합니다." #: data/mods/MMA/martial.json msgid "The Life and Work of Tiger Sauer" msgid_plural "The Life and Work of Tiger Sauer" -msgstr[0] "" +msgstr[0] "퀸스틀러를 위한 판처 쿤스트 안내서" #. ~ Description for {'str_sp': 'The Life and Work of Tiger Sauer'} #: data/mods/MMA/martial.json msgid "" "A biography of a combat cyborg agent detailing his philosophy and martial " "art." -msgstr "" +msgstr "전투용 사이보그 요원이 자신의 철학과 무예를 집대성한 자서전입니다." #: data/mods/MMA/martialarts.json msgid "Panzer Kunst" @@ -196200,7 +196482,7 @@ msgstr "" #: data/mods/MMA/martialarts.json msgid "Einzug Rüstungen" -msgstr "" +msgstr "아인추크 뤼스퉁겐" #. ~ Description of buff 'Einzug Rüstungen' for martial art '{'str': 'Panzer #. Kunst'}' @@ -196299,7 +196581,7 @@ msgstr "(이)가 뛰어올라 %s에게 섬머솔트 킥을 날립니다 #: data/mods/MMA/techniques.json msgid "Herzschlag" -msgstr "" +msgstr "헤르츠슐라크" #: data/mods/MMA/techniques.json #, c-format @@ -196313,7 +196595,7 @@ msgstr "" #: data/mods/MMA/techniques.json msgid "Geschoss Schlag" -msgstr "" +msgstr "게쉬오스 슐라크" #: data/mods/MMA/techniques.json #, c-format @@ -196867,6 +197149,11 @@ msgstr "물약" msgid "RUNES" msgstr "룬" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "마법 물품" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "마력 집중" @@ -197008,6 +197295,21 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "마법사의 바캉스 은신처" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "환수" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "드래곤" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "파충인" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "마법사의 비밀 지하 연구실" @@ -200845,6 +201147,16 @@ msgid "sledge hammer +2" msgid_plural "sledge hammer +2s" msgstr[0] "슬레지 해머 +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -201016,11 +201328,13 @@ msgid_plural "cavalry sabre +2s" msgstr[0] "기병용 세이버 +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "쇠지레 +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "쇠지레 +2" @@ -201066,11 +201380,13 @@ msgid_plural "combat knife +2s" msgstr[0] "컴뱃 나이프 +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "사냥용 칼 +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "사냥용 칼 +2" @@ -201215,6 +201531,16 @@ msgid "dao +2" msgid_plural "dao +2s" msgstr[0] "다오 +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -202055,6 +202381,66 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "앞면에 쇠지레가 그려진 큰 은화. 뒷면에 새겨진 주문을 외우면 활성화 됩니다." +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -203068,6 +203454,19 @@ msgstr "" "표지에 드래곤 브레스의 불길을 방패로 막아내는 그림이 그려진 가죽 제본 서적입니다. 괴물들의 가죽이나 비늘 따위로 보호구를 제작하는 " "여러 내용들이 담겨있습니다." +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -204035,6 +204434,11 @@ msgid "" "much more expensive." msgstr "오리칼쿰으로 만든 프레임. 강철보다 훨씬 튼튼하지만 훨씬 더 비쌉니다." +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "악마거미" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -204051,11 +204455,6 @@ msgstr "" "작은 개 크기이지만 아주 어린 새끼 거미입니다. 대격변 이전까지는 본 적이 없는 생물로, 붉은 색은 왜 이런 이름이 붙었는지 알게 " "해줍니다. 매우 빠르며, 커다란 송곳니에서는 맹독이 뚝뚝 흐릅니다." -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "악마거미" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -206911,10 +207310,20 @@ msgstr "" "어떤 사탕에 관한 광고지입니다. 부드러운 사탕으로 만들어진 빛나는 인간이 당신을 바라보며 공포에 사로잡힌 그림을 담고 있습니다. " "\"최초로 만들어진 1:1 크기 인간 캔디, 슈가킨! 당신은 진짜 괴물인가요? 저걸 남김없이 집어삼킬 수 있을까요?\"" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -209321,6 +209730,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "농장, 숲, 작은 마을 외에는 아무것도 없습니다. 권장하는 도시 크기는 1, 권장하는 도시 간격은 8 입니다." +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "Lua 저장/불러오기 테스트" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "Lua 저장/불러오기 API 테스트용 모드입니다." + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "플레이어 인식 아이콘 (HitButton_iso)" @@ -209343,6 +209761,79 @@ msgid "" "retrodays tileset." msgstr "개체가 플레이어를 보고 있을 때의 식별 아이콘을 추가합니다. RetroDays 타일셋과 어울리도록 만들었습니다." +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "스마트 홈 제어판" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" +"LCD 디스플레이가 달린 작은 제어판으로, 차고 문과 창문 커튼을 조작할 수 있습니다. 집에 전기가 들어오게 할 방법을 찾기 전까지는 " +"아무 쓸모도 없습니다." + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "문 및 셔터 제어" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "커튼 젖히기" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "커튼 닫기" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "차고 문 열기" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "차고 문 닫기" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "단말 전력 부족" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "신호 없음" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "단말 없음" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "신호음이 나지막하게 삑삑 울립니다." + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "단말 선택" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "스마트 홈 시스템" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "차고 문과 창문 커튼을 조작할 수 있는 제어판을 추가합니다." + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "민첩할수록 빠르게" @@ -209763,7 +210254,7 @@ msgstr "효과 지속시간 변경" #: data/raw/keybindings/edit_creature_effects.json msgid "Toggle force" -msgstr "" +msgstr "출력 표시" #: data/raw/keybindings/keybindings.json src/input.cpp src/messages.cpp msgid "Scroll up" @@ -210769,6 +211260,14 @@ msgstr "디버그 모드 토글" msgid "Debug Menu" msgstr "디버그 메뉴" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "Lua 콘솔" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "Lua 코드 다시 불러오기" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "냄새 지도 보기" @@ -211324,6 +211823,26 @@ msgstr "일기 .txt 파일로 내보내기" msgid "Add new page" msgstr "새 페이지 추가" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "명령어 편집" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "로그 위로 스크롤" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "로그 아래로 스크롤" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "최상단으로 이동" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "최하단으로 이동" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "와이드 디스플레이 활성화/비활성화" @@ -211482,8 +212001,32 @@ msgstr "터렛 자동조준 설정" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." -msgstr "%s등급 %i 달성하기 (%i/%i)" +msgid "Kill at least %i %s%s" +msgstr "%s%s (을)를 %i 개체 이상 처치" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "%s 의 처치 금지" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "%s%s(을)를 %i 개체 이하만 처치" + +#: src/achievement.cpp +msgid " (failed)" +msgstr " (실패)" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "%i 등급 %s 달성하기 (%i/%i)" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" +msgstr "%i 등급 %s 유지하기 (%i/%i)" #: src/achievement.cpp msgid "time of cataclysm" @@ -214056,7 +214599,7 @@ msgstr "가려운" #: src/artifact.cpp msgid "makes your skin itch slightly when it is close" -msgstr "가까이 가면 조금 가려워진다." +msgstr "가까이 있을 때 피부가 조금 근절거립니다." #: src/artifact.cpp msgid "glittering" @@ -217068,6 +217611,30 @@ msgstr "abcdefghijklmnopqrstuvwxyz" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "유일하게 아무나 트롤을 저질러도 용서가 되는 문장. 아무나 여기서 낙서를 할 수 있다. " +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "Ctrl+S 로 스크립트를 실행하고, Esc 로 취소합니다." + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "화살표 키로 텍스트 입력 위치를 이동합니다." + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "엔터 키로 새 줄을 삽입합니다." + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "엔터 키로 명령어를 추가하거나 편집하고, Esc 키로 종료합니다." + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "위/아래 화살표로 이전 선택지 중에서 선택합니다." + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "페이지업/페이지다운/홈/엔드 키로 출력 창을 스크롤합니다." + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -221968,6 +222535,10 @@ msgstr "정보..." msgid "Change [b]attery charge" msgstr "배터리 충전량 변경" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "Json 템플릿 내보내기 (J)" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "차량..." @@ -222084,6 +222655,10 @@ msgstr "메인 메뉴로 나가기" msgid "Player…" msgstr "플레이어..." +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "Lua 콘솔" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -222956,6 +223531,10 @@ msgstr "해당 지점에 차량이 없습니다." msgid "By how much? (in kJ, negative to discharge)" msgstr "얼마만큼 추가할지 킬로줄 단위로 입력해주세요. (음수의 경우 대신 감소시킵니다)" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "debug.log 에 기록되는 JSON 템플릿" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "의존성 상실: " @@ -235623,6 +236202,11 @@ msgstr "%s(이)가 당신의 손에서 그걸 쳐냅니다!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "%s에게 %s(을)를 먹이려 했지만, 사라져버립니다!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "개 사료를 먹이려 했지만, 놈이 당신의 손가락을 물었습니다!" @@ -241504,6 +242088,11 @@ msgstr "오늘의 메시지" msgid "Create World" msgstr "월드 생성" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "Lua 필요!" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "버그가 있나요? 제안하고 싶은게 있나요? 오늘의 메시지에 있는 링크로 들어와주세요." @@ -241765,6 +242354,13 @@ msgstr "정말로 %s(을)를 지웁니까?" msgid "Sorry, something went wrong." msgstr "죄송합니다, 뭔가 잘못되었습니다." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "%s (은)는 Lua 를 지원하는 게임 빌드를 필요로 합니다!" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -245573,6 +246169,15 @@ msgstr[0] "충돌" msgid "Mod version" msgstr "모드버전" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "%s: API 버전 %s\n" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "Lua 필요" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "모드 정보 경로" @@ -248543,11 +249148,6 @@ msgstr "피로로 인한 기분 최대치:" msgid "Focus trends towards:" msgstr "집중 수준 변동 경향:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "인간" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -251201,6 +251801,14 @@ msgstr "SDL" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "SDL (Simple DirectMedia Layer)와 타일, 타일셋 그리고 소리에 관련된 메시지입니다." +#: src/options.cpp +msgid "Lua" +msgstr "Lua" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "Lua 스크립트로 발생한 메시지입니다." + #: src/options.cpp msgid "General" msgstr "일반 설정" @@ -252315,6 +252923,16 @@ msgstr "애니메이션 지연시간" msgid "The amount of time to pause between animation frames in ms." msgstr "애니메이션 프레임 사이의 정지시간을 설정합니다. (단위: ms)" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "총탄 선으로 그리기" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "활성화되면 총탄 이미지가 선으로 표시되어, 애니메이션이 1프레임만 지속됩니다." + #: src/options.cpp msgid "Blinking effects speed" msgstr "깜빡임 효과 속도" @@ -252391,64 +253009,64 @@ msgid "Font height" msgstr "폰트 높이" #: src/options.cpp -msgid "Set the font height. Requires restart." -msgstr "폰트 높이를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the font height. Requires restart." +msgstr "폰트 높이를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Font size" msgstr "폰트 크기" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "폰트 크기를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the font size. Requires restart." +msgstr "폰트 크기를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Map font width" msgstr "지도 폰트 너비" #: src/options.cpp -msgid "Set the map font width. Requires restart." -msgstr "지도 너비를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the map font width. Requires restart." +msgstr "지도 폰트 너비를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Map font height" msgstr "지도 폰트 높이" #: src/options.cpp -msgid "Set the map font height. Requires restart." -msgstr "지도 폰트 높이를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the map font height. Requires restart." +msgstr "지도 폰트 높이를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Map font size" msgstr "지도 폰트 크기" #: src/options.cpp -msgid "Set the map font size. Requires restart." -msgstr "지도 폰트 크기를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the map font size. Requires restart." +msgstr "지도 폰트 크기를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Overmap font width" msgstr "오버맵 폰트 너비" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." -msgstr "오버맵 폰트 너비를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the overmap font width. Requires restart." +msgstr "오버맵 폰트 너비를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Overmap font height" msgstr "오버맵 폰트 높이" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." -msgstr "오버맵 폰트 높이를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the overmap font height. Requires restart." +msgstr "오버맵 폰트 높이를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Overmap font size" msgstr "오버맵 폰트 크기" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." -msgstr "오버맵 폰트 크기를 설정합니다. 재시작해야 적용됩니다." +msgid "Set the overmap font size. Requires restart." +msgstr "오버맵 폰트 크기를 설정합니다. 재시작을 필요로 합니다." #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -255569,7 +256187,7 @@ msgstr "명중" #: src/ranged.cpp msgid "Regular" -msgstr "통상 조준" +msgstr "통상" #: src/ranged.cpp #, c-format @@ -255578,7 +256196,7 @@ msgstr "[%c] 조준 / 발사" #: src/ranged.cpp msgid "Careful" -msgstr "신중한 조준" +msgstr "신중한" #: src/ranged.cpp #, c-format @@ -255587,7 +256205,7 @@ msgstr "[%c] 조준 / 발사" #: src/ranged.cpp msgid "Precise" -msgstr "정밀 조준" +msgstr "정밀" #: src/ranged.cpp #, c-format @@ -255894,7 +256512,7 @@ msgstr "0.0 % 실패율" #: src/ranged.cpp #, c-format msgid "Effective Spell Radius: %s%s" -msgstr "" +msgstr "유효 주문 반경: %s%s" #: src/ranged.cpp msgid " WARNING! IN RANGE" @@ -260077,6 +260695,11 @@ msgstr "없는 모드" msgid " [%s]" msgstr " [%s]" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "(Lua 필요)" + #: src/worldfactory.cpp msgid "N/A" msgstr "해당없음" diff --git a/lang/po/nb.po b/lang/po/nb.po index 13b2ca3fac8b..5a26aec1b4fd 100644 --- a/lang/po/nb.po +++ b/lang/po/nb.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2020 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2020\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Norwegian Bokmål (https://app.transifex.com/bn-team/teams/113585/nb/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1490,10 +1490,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3856,10 +3864,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -8002,6 +8024,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "Taket kollapser på deg!" @@ -21882,34 +21915,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21918,30 +22007,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21950,6 +22088,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -21958,6 +22104,13 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -21966,18 +22119,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -47696,12 +47882,9 @@ msgstr[1] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Håndlagde uautoriserte duplikater av Rivtech 20x66mm hylseløse flechette " -"patroner. Ved at disse er hylseløse patroner, så kan dem ikke demonteres " -"eller lades om." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -47712,12 +47895,9 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Håndlagde bootleg duplikater av Rivtech 20x66mm caseless buckshot patroner. " -"Ved at disse er hylseløse patroner, så kan dem ikke demonteres eller lades " -"om." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -47729,12 +47909,9 @@ msgstr[1] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Håndlaget uautoriserte duplikater av Rivtech 20x66mm hylseløse solid-" -"prosjektil patroner. Ved at disse er hylseløse patroner, så kan dem ikke " -"demonteres eller lades om." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -49317,18 +49494,57 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -49666,45 +49882,45 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "93mm ett-trinns høy-eksplosiv ammunisjon for RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "64 mm / 105 mm høyeksplosiv tandem-ammunisjon til RPG-7." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "105 mm termobar ammunisjon til RPG-7." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -71730,6 +71946,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -72806,6 +73066,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -75205,6 +75466,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -81522,6 +81784,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -111618,12 +111881,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -112261,12 +112518,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -122420,7 +122671,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -130230,10 +130482,6 @@ msgstr "monster" msgid "demon" msgstr "demon" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "skrekk" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "ubeskrivelig beist" @@ -143563,6 +143811,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -143599,6 +143857,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -173377,6 +173649,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -183262,6 +183541,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -195252,6 +195538,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -195379,6 +195670,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -199216,6 +199525,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -199421,12 +199742,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -199481,12 +199804,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -199660,6 +199985,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -200548,6 +200885,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -201622,6 +202031,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -202697,6 +203120,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -202712,12 +203141,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -205543,10 +205966,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -207869,6 +208304,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -207891,6 +208335,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -209317,6 +209833,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -209872,6 +210396,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -210030,7 +210574,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -215572,6 +216140,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -220373,6 +220965,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -220489,6 +221085,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -221355,6 +221955,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -233653,6 +234257,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -239511,6 +240120,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -239771,6 +240385,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -243482,6 +244103,15 @@ msgstr[1] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -246439,12 +247069,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -249040,6 +249664,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Generelt" @@ -250114,6 +250746,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -250188,7 +250830,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -250196,7 +250838,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -250204,7 +250846,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -250212,7 +250854,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -250220,7 +250862,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -250228,7 +250870,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -250236,7 +250878,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -250244,7 +250886,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -257793,6 +258435,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/nl.po b/lang/po/nl.po index 3e262234e2e4..7e59ce63bf2e 100644 --- a/lang/po/nl.po +++ b/lang/po/nl.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2021 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2021\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Dutch (https://app.transifex.com/bn-team/teams/113585/nl/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1494,10 +1494,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3860,10 +3868,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -8002,6 +8024,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21875,34 +21908,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21911,30 +22000,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "een fungus" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "een insect" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21943,6 +22081,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "een zombie" @@ -21951,6 +22097,13 @@ msgstr "een zombie" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -21959,18 +22112,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -47549,8 +47735,8 @@ msgstr[1] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47562,8 +47748,8 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47576,8 +47762,8 @@ msgstr[1] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49048,18 +49234,57 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -49392,45 +49617,45 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -71452,6 +71677,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -72528,6 +72797,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -74927,6 +75197,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -81238,6 +81509,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -111239,12 +111511,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -111882,12 +112148,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -122021,7 +122281,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -129825,10 +130086,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -143158,6 +143415,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -143194,6 +143461,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -172954,6 +173235,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -182839,6 +183127,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -194831,6 +195126,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -194958,6 +195258,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -198795,6 +199113,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -199000,12 +199330,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -199060,12 +199392,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -199239,6 +199573,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -200127,6 +200473,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -201201,6 +201619,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -202276,6 +202708,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -202291,12 +202729,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -205123,10 +205555,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -207448,6 +207892,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -207470,6 +207923,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -208896,6 +209421,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -209451,6 +209984,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -209609,7 +210162,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -215151,6 +215728,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -219952,6 +220553,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -220068,6 +220673,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -220934,6 +221543,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -233237,6 +233850,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -239095,6 +239713,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -239355,6 +239978,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "Het spijt ons, maar er is iet fout gegaan." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -243066,6 +243696,15 @@ msgstr[1] "" msgid "Mod version" msgstr "Modversie" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -246023,12 +246662,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -248626,6 +249259,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Algemeen" @@ -249710,6 +250351,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -249784,7 +250435,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -249792,7 +250443,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -249800,7 +250451,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -249808,7 +250459,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -249816,7 +250467,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -249824,7 +250475,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -249832,7 +250483,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -249840,7 +250491,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -257389,6 +258040,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "N/A" diff --git a/lang/po/pl_PL.po b/lang/po/pl_PL.po index 22597ee2b36b..2f005aa552e4 100644 --- a/lang/po/pl_PL.po +++ b/lang/po/pl_PL.po @@ -1,12 +1,12 @@ # # Translators: -# f91d578b5f6d79f8731c18a004205359_9ca50b9, 2022 +# f91d578b5f6d79f8731c18a004205359_9ca50b9, 2023 # Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Coolthulhu , 2023\n" "Language-Team: Polish (Poland) (https://app.transifex.com/bn-team/teams/113585/pl_PL/)\n" "MIME-Version: 1.0\n" @@ -1621,10 +1621,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4229,10 +4237,26 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "wyrostek" @@ -8493,6 +8517,17 @@ msgstr "Nie.... możesz... oddychać... Astma!" msgid "You're winded." msgstr "Jesteś pozbawiony tchu." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "Dach zapada się na ciebie!" @@ -23409,34 +23444,106 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -23445,30 +23552,93 @@ msgstr "" msgid "plop." msgstr "plop." +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "grzyb" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "insekt" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -23477,6 +23647,16 @@ msgstr "" msgid "rustle." msgstr "szelest." +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "zombie" +msgstr[1] "zombie" +msgstr[2] "zombie" +msgstr[3] "zombie" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "zombie" @@ -23485,6 +23665,15 @@ msgstr "zombie" msgid "shuffling." msgstr "szuranie." +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -23493,18 +23682,61 @@ msgstr "" msgid "mechanical whirring." msgstr "mechaniczne brzęczenie." +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "wynaturzenie" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "człowiek" +msgstr[1] "ludzie" +msgstr[2] "ludzie" +msgstr[3] "ludzie" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -52144,12 +52376,9 @@ msgstr[3] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Ręcznie robione pirackie duplikaty bezłuskowych naboi do strzelb Rivtech " -"20x66mm w wersji strzałkowej. Jako bezłuskowe nie mogą być rozłożone na " -"części ani regenerowane." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -52162,12 +52391,9 @@ msgstr[3] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Ręcznie robione pirackie duplikaty bezłuskowych naboi do strzelb Rivtech " -"20x66mm w wersji śrutowej. Jako bezłuskowe nie mogą być rozłożone na części " -"ani regenerowane." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -52181,12 +52407,9 @@ msgstr[3] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Ręcznie robione pirackie duplikaty bezłuskowych naboi do strzelb Rivtech " -"20x66mm w wersji pełnych kul typu brenka. Jako bezłuskowe nie mogą być " -"rozłożone na części ani regenerowane." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -54065,21 +54288,64 @@ msgstr "" "dymnych." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"Pirackie podróbki bezłuskowej amunicji Rivtech 8x40. Jako bezłuskowe nie " -"mogą być rozłożone na części ani regenerowane. " + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -54521,14 +54787,14 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "Tuba małych kulek do paintballa. Praktycznie nie zadają obrażeń." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "" @@ -54536,40 +54802,40 @@ msgstr "" "RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -81302,6 +81568,58 @@ msgstr "" "Jaja w zalewie octowej. Dość słone, ale smakują nieźle i mają długą " "trwałość." +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -82666,6 +82984,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -85630,6 +85949,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "guma do żucia" @@ -93419,6 +93739,7 @@ msgstr "Chrupiące pyszne gofry z syropem klonowym obsypane kawałkami owoców." #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "krakers" @@ -129830,14 +130151,6 @@ msgstr "" "Agresywny zmutowany rodzaj padalca, bladożółty z powodu podziemnego życia. " "Roi się pod ziemią i jest znany z tego, że jest plagą kanałów ściekowych." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -130639,14 +130952,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "zombie" -msgstr[1] "zombie" -msgstr[2] "zombie" -msgstr[3] "zombie" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -141781,7 +142086,8 @@ msgid "I'll kill you if you don't." msgstr "W przeciwnym wypadku cię zabiję." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "Nieważne." @@ -150007,10 +150313,6 @@ msgstr "potwór" msgid "demon" msgstr "demon" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "horror" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "nieopisana bestia" @@ -164434,6 +164736,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -164470,6 +164782,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -197214,6 +197540,15 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -207707,6 +208042,15 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -221330,6 +221674,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -221457,6 +221806,30 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -225563,6 +225936,22 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -225836,6 +226225,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -225844,6 +226234,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -225916,6 +226307,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -225924,6 +226316,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -226155,6 +226548,22 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -227161,6 +227570,102 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -228423,6 +228928,22 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -229750,6 +230271,14 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -229767,14 +230296,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -233059,10 +233580,26 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -235603,6 +236140,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -235625,6 +236171,80 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "SpeedyDex" @@ -237117,6 +237737,14 @@ msgstr "Przełącz Tryb Debuggowania" msgid "Debug Menu" msgstr "Menu Debugowania" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Wyświetl Mapę Zapachów" @@ -237672,6 +238300,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -237830,7 +238478,31 @@ msgstr "Ustaw tryb celowania wieżyczek" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -243553,6 +244225,30 @@ msgstr "abcdefghijklmnopqrstuvwxyz" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -248497,6 +249193,10 @@ msgstr "Info…" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -248613,6 +249313,10 @@ msgstr "Wyjdź do Głównego Menu" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -249484,6 +250188,10 @@ msgstr "Nie ma tam pojazdu." msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -262079,6 +262787,11 @@ msgstr "%s wytrąca ci je z ręki!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "Próbujesz nakarmić %s używając %s, ale to znika!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "Chcesz nakarmić go psim żarciem, ale gryzie cię w palce!" @@ -268043,6 +268756,11 @@ msgstr "" msgid "Create World" msgstr "Stwórz Świat" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "Błędy? Sugestie? Użyj linków w Wiadomości Dnia by je zgłosić." @@ -268305,6 +269023,13 @@ msgstr "Jesteś pewien że chcesz skasować %s?" msgid "Sorry, something went wrong." msgstr "Wybacz, coś poszło nie tak." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -272054,6 +272779,15 @@ msgstr[3] "" msgid "Mod version" msgstr "Wersja moda" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -275045,14 +275779,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "Skupienie dąży do:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "człowiek" -msgstr[1] "ludzie" -msgstr[2] "ludzie" -msgstr[3] "ludzie" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -277718,6 +278444,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Ogólne" @@ -278879,6 +279613,16 @@ msgstr "Opóźnienie animacji" msgid "The amount of time to pause between animation frames in ms." msgstr "Czas pauzy pomiędzy animowanymi klatkami w ms." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -278955,64 +279699,64 @@ msgid "Font height" msgstr "Wysokość czcionki" #: src/options.cpp -msgid "Set the font height. Requires restart." -msgstr "" +msgid "Set the font height. Requires restart." +msgstr "Ustawia wysokość czcionki. Wymagany restart." #: src/options.cpp msgid "Font size" msgstr "Rozmiar czcionki" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "" +msgid "Set the font size. Requires restart." +msgstr "Ustawia rozmiar czcionki. Wymagany restart." #: src/options.cpp msgid "Map font width" msgstr "Szerokość czcionki mapy" #: src/options.cpp -msgid "Set the map font width. Requires restart." -msgstr "" +msgid "Set the map font width. Requires restart." +msgstr "Ustawia szerokość czcionki mapy. Wymagany restart." #: src/options.cpp msgid "Map font height" msgstr "Wysokość czcionki mapy" #: src/options.cpp -msgid "Set the map font height. Requires restart." -msgstr "" +msgid "Set the map font height. Requires restart." +msgstr "Ustawia wysokość czcionki mapy. Wymagany restart." #: src/options.cpp msgid "Map font size" msgstr "Rozmiar czcionki mapy" #: src/options.cpp -msgid "Set the map font size. Requires restart." -msgstr "" +msgid "Set the map font size. Requires restart." +msgstr "Ustawia rozmiar czcionki mapy. Wymagany restart." #: src/options.cpp msgid "Overmap font width" msgstr "Szerokość czcionki mapy zasadniczej" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." -msgstr "" +msgid "Set the overmap font width. Requires restart." +msgstr "Ustawia szerokość czcionki mapy zasadniczej. Wymagany restart." #: src/options.cpp msgid "Overmap font height" msgstr "Wysokość czcionki mapy zasadniczej" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." -msgstr "" +msgid "Set the overmap font height. Requires restart." +msgstr "Ustawia wysokość czcionki mapy zasadniczej. Wymagany restart." #: src/options.cpp msgid "Overmap font size" msgstr "Rozmiar czcionki mapy zasadniczej" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." -msgstr "" +msgid "Set the overmap font size. Requires restart." +msgstr "Ustawia rozmiar czcionki mapy zasadniczej. Wymagany restart." #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -286785,6 +287529,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "N/A" diff --git a/lang/po/pt_BR.po b/lang/po/pt_BR.po index 4b19f7987647..59cfd6555644 100644 --- a/lang/po/pt_BR.po +++ b/lang/po/pt_BR.po @@ -1,13 +1,13 @@ # # Translators: -# Jungle Man , 2020 -# rockygargoyle , 2020 +# Jungle Man , 2023 +# rockygargoyle , 2023 # Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Coolthulhu , 2023\n" "Language-Team: Portuguese (Brazil) (https://app.transifex.com/bn-team/teams/113585/pt_BR/)\n" "MIME-Version: 1.0\n" @@ -1573,10 +1573,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4159,10 +4167,25 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "R. Apêndice apêndice pé" @@ -8475,6 +8498,17 @@ msgstr "" msgid "You're winded." msgstr "Você está sem fôlego." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "O teto desmorona em você!" @@ -23401,34 +23435,98 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -23437,30 +23535,86 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "um fungo" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "um inseto" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -23469,6 +23623,15 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "um zumbi" @@ -23477,6 +23640,14 @@ msgstr "um zumbi" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -23485,18 +23656,56 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "uma aberração" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "humano" +msgstr[1] "humanos" +msgstr[2] "humanos" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -51392,12 +51601,9 @@ msgstr[2] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Duplicatas piratas de munições sem cartucho tipo flechette para espingardas " -"Rivtech 20x66mm. Sendo uma munição sem invólucros, ela não pode ser " -"desmontada ou recarregada." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -51409,12 +51615,9 @@ msgstr[2] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Duplicatas piratas de munições sem cartucho do tipo chumbo grosso para " -"espingardas Rivtech 20x66mm. Sendo uma munição sem invólucros, ela não pode " -"ser desmontada ou recarregada." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -51427,11 +51630,9 @@ msgstr[2] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Duplicatas piratas de projéteis Rivtech 20x66mm sólidos sem invólucro. Sendo" -" uma munição sem invólucro, ela não pode ser desmontada ou recarregada." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -53210,20 +53411,60 @@ msgstr "" "tropas." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm JHP, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -" Bootleg duplica de rodadas sem caixa Rivtech 8x40mm. Sendo rodadassemcaixa," -" estas não podem ser desmontadas ou recarregadas." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -53641,49 +53882,49 @@ msgstr "" " Um tubo de pequenas bolas de tinta. Eles praticamente não causam danos." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Uma munição alto-explosiva de único estágio de 93mm para o RPG-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "Munição alto-explosiva de 64mm/105mm para o RPG-7." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "Munição termobárica de 105mm para um RPG-7." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -79118,6 +79359,54 @@ msgid "" msgstr "" " Um ovo em conserva. Um pouco salgado, mas bom gosto e dura muito tempo." +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -80417,6 +80706,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -83198,6 +83488,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "goma de mascar" @@ -90523,6 +90814,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -125319,13 +125611,6 @@ msgstr "" " sua vida subterrânea. Enxada sob o solo e é nomeado por seu " "hábitodeinfestar linhas de esgoto." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -126083,13 +126368,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -137139,7 +137417,8 @@ msgid "I'll kill you if you don't." msgstr "Eu vou te matar se você não fizer." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "Deixa pra lá." @@ -145371,10 +145650,6 @@ msgstr "monstro" msgid "demon" msgstr "demônio" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "Horror" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "besta indescritível" @@ -159777,6 +160052,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -159813,6 +160098,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -192117,6 +192416,14 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -202339,6 +202646,14 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -215190,6 +215505,11 @@ msgstr "POÇÕES" msgid "RUNES" msgstr "RUNAS" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -215317,6 +215637,27 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -219294,6 +219635,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -219533,6 +219888,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -219540,6 +219896,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -219603,6 +219960,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -219610,6 +219968,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -219812,6 +220171,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -220762,6 +221135,90 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -221931,6 +222388,21 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -223132,6 +223604,13 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -223148,13 +223627,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -226319,10 +226791,24 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -228813,6 +229299,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -228835,6 +229330,79 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -230334,6 +230902,14 @@ msgstr "Ativar Modo de Depuração" msgid "Debug Menu" msgstr "Menu de Depuração" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Visualizar Scentmap" @@ -230889,6 +231465,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -231047,7 +231643,31 @@ msgstr "Definir modos de mira da torre" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -236706,6 +237326,30 @@ msgstr "a B C D e F G H I J K L M N o p q R S T U V W x y Z" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "Pesquisa de inclinação e medição de carga" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -241572,6 +242216,10 @@ msgstr "Info..." msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -241688,6 +242336,10 @@ msgstr "Sair para o menu principal" msgid "Player…" msgstr "Jogador..." +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -242566,6 +243218,10 @@ msgstr "Não há veículo lá." msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -255063,6 +255719,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "Você quer alimentar a comida de cachorro, mas ela morde os dedos!" @@ -260984,6 +261645,11 @@ msgstr "" msgid "Create World" msgstr "Criar Mundo" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "Problemas? Sugestões? Use os links no MOTD para reportá-los." @@ -261250,6 +261916,13 @@ msgstr "Tem certeza de que deseja apagar %s?" msgid "Sorry, something went wrong." msgstr "Desculpe, algo deu errado." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -264984,6 +265657,15 @@ msgstr[2] "" msgid "Mod version" msgstr "Versão de Mod de Dependência do Mantenedor do Autor" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -267965,13 +268647,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "humano" -msgstr[1] "humanos" -msgstr[2] "humanos" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -270616,6 +271291,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Geral" @@ -271770,6 +272453,16 @@ msgstr "Atraso da animação" msgid "The amount of time to pause between animation frames in ms." msgstr "Quanto tempo deve pausar entre os frames da animação em ms." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -271846,7 +272539,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -271854,7 +272547,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -271862,7 +272555,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -271870,7 +272563,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -271878,7 +272571,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -271886,7 +272579,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -271894,7 +272587,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -271902,7 +272595,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -279657,6 +280350,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "N/A" diff --git a/lang/po/ru_RU.po b/lang/po/ru_RU.po index 6b9ef90559a0..614b9364a0c8 100644 --- a/lang/po/ru_RU.po +++ b/lang/po/ru_RU.po @@ -1,32 +1,32 @@ # # Translators: -# Павел Трофимов , 2021 -# Ilya Somov , 2021 -# 4nonch , 2021 -# Алексей Морковин , 2021 -# Ivan Vlasov , 2021 -# Ekaterina Aleksashkina , 2021 -# Denis Popov , 2021 -# Валентин Литовченко , 2021 -# Fastro, 2022 -# Александр Шкаликов, 2022 -# Firestorm_01 , 2022 -# Gamp Forest, 2022 -# Aquilo, 2022 -# Никита Абрамов, 2022 -# 8street, 2022 -# Vlados , 2022 +# Gamp Forest, 2023 +# Fastro, 2023 +# Павел Трофимов , 2023 +# Aquilo, 2023 # Olanti , 2023 +# 4nonch , 2023 # Izergaer, 2023 +# Валентин Литовченко , 2023 +# Denis Popov , 2023 +# Алексей Морковин , 2023 +# Александр Шкаликов, 2023 +# 8street, 2023 +# Никита Абрамов, 2023 +# Ilya Somov , 2023 +# Ivan Vlasov , 2023 +# Firestorm_01 , 2023 +# Vorpal Void , 2023 +# Vlados , 2023 # Дмитрий Кириллов , 2023 +# Ekaterina Aleksashkina , 2023 # Coolthulhu , 2023 -# Vorpal Void , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Vorpal Void , 2023\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Russian (Russia) (https://app.transifex.com/bn-team/teams/113585/ru_RU/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -2186,10 +2186,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "[Бой] Один готов, миллиарды на очереди…" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "[Бой] Грубое пробуждение" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -4959,12 +4967,25 @@ msgstr "КБМ: Вечный генератор" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" -"Внутри вас установлен вечный генератор, питающийся от нонсенсолеума. При " -"активации мощность генератора удваивается. Если вы видите это, значит вы " -"использовали режим отладки." + +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" #: data/json/body_parts.json msgid "appendix" @@ -9301,6 +9322,17 @@ msgstr "Вы не можете вдохнуть… Приступ астмы!" msgid "You're winded." msgstr "Вы запыхались." +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "На вас обрушился потолок!" @@ -25124,34 +25156,106 @@ msgstr[1] "Если вы это видите, то это баг." msgstr[2] "Если вы это видите, то это баг." msgstr[3] "Если вы это видите, то это баг." +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "млекопитающее" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "амфибия" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "птица" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "рептилия" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "рыба" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "мутант" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "потустороннее существо" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "сгусток" +msgstr[1] "сгустка" +msgstr[2] "сгустков" +msgstr[3] "сгустки" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "сгусток" @@ -25160,30 +25264,93 @@ msgstr "сгусток" msgid "plop." msgstr "плюх." +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "грибы" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "растение-пиявочник" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "насекомое" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "паук" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "растение" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "моллюск" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "червь" @@ -25192,6 +25359,16 @@ msgstr "червь" msgid "rustle." msgstr "шелест." +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "зомби" +msgstr[1] "зомби" +msgstr[2] "зомби" +msgstr[3] "зомби" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "зомби" @@ -25200,6 +25377,15 @@ msgstr "зомби" msgid "shuffling." msgstr "шарканье." +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "робот" @@ -25208,18 +25394,61 @@ msgstr "робот" msgid "mechanical whirring." msgstr "механическое жужжание." +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "ужас" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "аберрация" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "человек" +msgstr[1] "человека" +msgstr[2] "человек" +msgstr[3] "человек" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "человек" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -29489,7 +29718,7 @@ msgstr "«Шпок!»" #: data/json/traps.json data/json/items/ammo_types.json msgid "glass shards" -msgstr "осколок стекла" +msgstr "осколка стекла" #. ~ Trap-vehicle collision message for trap 'glass shards' #: data/json/traps.json @@ -42324,7 +42553,7 @@ msgstr ".45-70" #: data/json/items/ammo_types.json msgid "nails" -msgstr "гвозди" +msgstr "гвоздей" #: data/json/items/ammo_types.json msgid "barb" @@ -42332,7 +42561,7 @@ msgstr "колючка" #: data/json/items/ammo_types.json msgid "BBs" -msgstr "стальные пульки" +msgstr "стальных пулек" #: data/json/items/ammo_types.json msgid "bolts" @@ -55455,11 +55684,9 @@ msgstr[3] "патроны 20x66 мм (флешетты, самодельный)" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Нелицензионные кустарные копии безгильзовых флешеттных патронов 20x66 мм от " -"«Ривтех». Безгильзовые патроны нельзя разобрать или переснарядить." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -55472,11 +55699,9 @@ msgstr[3] "патроны 20x66мм (картечь, самодельный)" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Нелицензионные кустарные копии безгильзовых картечных патронов 20x66 мм от " -"«Ривтех». Безгильзовые патроны нельзя разобрать или переснарядить." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -55490,11 +55715,9 @@ msgstr[3] "патроны 20x66 мм (жакан, самодельный)" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Нелицензионные кустарные копии безгильзовых пулевых патронов 20x66 мм от " -"«Ривтех». Безгильзовые патроны нельзя разобрать или переснарядить." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -57509,21 +57732,64 @@ msgstr "" "передвижения войск." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" -msgstr[0] "патрон 8x40 мм ЭП (самопальный)" -msgstr[1] "патрона 8x40 мм ЭП (самопальный)" -msgstr[2] "патронов 8x40 мм ЭП (самопальный)" -msgstr[3] "патроны 8x40 мм ЭП (самопальный)" - -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" -"Нелицензионные копии безгильзовых патронов 8x40 мм от «Ривтех». Безгильзовые" -" патроны нельзя разобрать или переснарядить." + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -57972,53 +58238,53 @@ msgstr "" "повреждений." #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" -msgstr[0] "ракета PG-7VL 93мм" -msgstr[1] "ракеты PG-7VL 93мм" -msgstr[2] "ракет PG-7VL 93мм" -msgstr[3] "ракеты PG-7VL 93мм" - -#. ~ Description for PG-7VL 93mm rocket +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "93-мм одноступенчатый фугасный боеприпас для РПГ-7." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" -msgstr[0] "ракета PG-7VL 64 мм/105 мм" -msgstr[1] "ракеты PG-7VL 64 мм/105 мм" -msgstr[2] "ракет PG-7VL 64 мм/105 мм" -msgstr[3] "ракеты PG-7VL 64 мм/105 мм" - -#. ~ Description for PG-7VR 64mm/105mm rocket +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "Фугасный тандемный 64 мм/105 мм боеприпас для РПГ-7." #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" -msgstr[0] "ракета TBG-7V 105 мм" -msgstr[1] "ракеты TBG-7V 105 мм" -msgstr[2] "ракет TBG-7V 105 мм" -msgstr[3] "ракеты TBG-7V 105 мм" - -#. ~ Description for TBG-7V 105mm rocket +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "105 мм термобарический боеприпас для РПГ-7." #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" -msgstr[0] "ракета OG-7V 40 мм" -msgstr[1] "ракеты OG-7V 40 мм" -msgstr[2] "ракет OG-7V 40 мм" -msgstr[3] "ракеты OG-7V 40 мм" - -#. ~ Description for OG-7V 40mm rocket +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -86061,6 +86327,58 @@ msgstr "" "Маринованное яйцо. Довольно солёное, однако очень вкусное и хранится долгое " "время." +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -87436,6 +87754,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "печенье" @@ -90481,6 +90800,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "жевательная резинка" @@ -98448,6 +98768,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "крекер" @@ -137176,14 +137497,6 @@ msgstr "" " жизни. Обитает под землёй и назван так из-за привычки паразитировать в " "канализации." -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "сгусток" -msgstr[1] "сгустка" -msgstr[2] "сгустков" -msgstr[3] "сгустки" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -138043,14 +138356,6 @@ msgstr "" "Обезображенное человеческое тело. Его кожа превратилась в твёрдую, язвенную " "ткань со шрамами." -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "зомби" -msgstr[1] "зомби" -msgstr[2] "зомби" -msgstr[3] "зомби" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -149814,7 +150119,8 @@ msgid "I'll kill you if you don't." msgstr "Я убью тебя если ты не сделаешь этого." #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "Забудь." @@ -158540,10 +158846,6 @@ msgstr "монстр" msgid "demon" msgstr "демон" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "ужас" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "неописуемый монстр" @@ -174962,6 +175264,16 @@ msgstr "" "Погоди. Мне всё равно, как ты сюда пробрался, но дальше ты не пройдёшь. " "Убирайся." +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "Стоп! Что??" @@ -174999,6 +175311,20 @@ msgstr "Что там про защитное снаряжение?" msgid "Alright, I'm leaving." msgstr "Хорошо, я ухожу." +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "Нет. Теперь уходи." @@ -211718,6 +212044,15 @@ msgstr "" "Восстановленный дрон, переоборудованный в летающий обогреватель. Он " "постоянно испускает струю тепла, нагревая замкнутое пространство." +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "разумное животное, созданное человеком до Катаклизма" @@ -223469,6 +223804,15 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "Управление доступом в операционную DinoLab" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "динозавр" @@ -238039,6 +238383,11 @@ msgstr "ЗЕЛЬЯ" msgid "RUNES" msgstr "РУНЫ" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "сосредоточение маны" @@ -238188,6 +238537,30 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "Отпуск в убежище волшебника" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "Подвал секретного кабинета волшебника" @@ -242734,6 +243107,22 @@ msgstr[1] "кувалды +2" msgstr[2] "кувалд +2" msgstr[3] "кувалды +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -243007,6 +243396,7 @@ msgstr[2] "кавалерийских сабель +2" msgstr[3] "кавалерийские сабли +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "ломик +1" @@ -243015,6 +243405,7 @@ msgstr[2] "ломиков +1" msgstr[3] "ломики +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "ломик +2" @@ -243087,6 +243478,7 @@ msgstr[2] "боевых ножей +2" msgstr[3] "боевые ножи +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "охотничий нож +1" @@ -243095,6 +243487,7 @@ msgstr[2] "охотничьих ножей +1" msgstr[3] "охотничьи ножи +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "охотничий нож +2" @@ -243326,6 +243719,22 @@ msgstr[1] "дао +2" msgstr[2] "дао +2" msgstr[3] "дао +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -244470,6 +244879,102 @@ msgstr "" "превращается в предмет, изображенный на лицевой стороне, в нашем случае, " "ломик." +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -245850,6 +246355,22 @@ msgstr "" "пламени. Внутри множество способ по превращению шкур и кожи монстров в " "доспехи." +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -247248,6 +247769,14 @@ msgid "" msgstr "" "Рама из орихалка. Заметно прочнее стали, но соответственно заметно дороже." +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "демонический паук" +msgstr[1] "демонических паука" +msgstr[2] "демонических пауков" +msgstr[3] "демонические пауки" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -247268,14 +247797,6 @@ msgstr "" " Вы его так назвали из-за красного цвета. До Катаклизма вы никогда не видели" " ничего похожего. Он быстрый, а с длинных клыков капает яд." -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "демонический паук" -msgstr[1] "демонических паука" -msgstr[2] "демонических пауков" -msgstr[3] "демонические пауки" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -250817,10 +251338,26 @@ msgstr "" "конфета размером с человека! Настоящее ли вы чудовище? Сумеете ли его " "съесть?»" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "хлюп." +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "хлоп." @@ -253742,6 +254279,15 @@ msgstr "" "Выживайте в глуши! Ничего, кроме ферм, лесов и деревень. Рекомендуется " "установить размер городов на 1 и расстояние между городами на 8." +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "значок видит-ли-игрока, HitButton_iso" @@ -253768,6 +254314,80 @@ msgstr "" "Добавляет значок, если существо видит игрока. Предназначен для тайлсета " "retrodays." +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "Быстроловкость" @@ -255297,6 +255917,14 @@ msgstr "Переключить режим отладки" msgid "Debug Menu" msgstr "Меню отладки" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "Карта запахов" @@ -255852,6 +256480,26 @@ msgstr "Экспорт дневника в .txt" msgid "Add new page" msgstr "Добавить новую страницу" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "Переключить широкий экран" @@ -256010,8 +256658,32 @@ msgstr "Установить режимы прицеливания туреле #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." -msgstr "Достигнут %s уровень навыка в %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" +msgstr "" #: src/achievement.cpp msgid "time of cataclysm" @@ -261919,6 +262591,30 @@ msgstr "абвгдеёжзийклмнопрстуфхцчшщъыьэюя" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -266972,6 +267668,10 @@ msgstr "Информация…" msgid "Change [b]attery charge" msgstr "[b] Изменить заряд батареи" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "Транспорт…" @@ -267088,6 +267788,10 @@ msgstr "Выйти в главное меню" msgid "Player…" msgstr "Игрок…" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -267970,6 +268674,10 @@ msgstr "Тут нет машины." msgid "By how much? (in kJ, negative to discharge)" msgstr "Насколько? (в кДж, отрицательное значение для разрядки)" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "Отсутствующая зависимость (зависимости): " @@ -281089,6 +281797,11 @@ msgstr "%s выбивает его у вас из рук!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "Вы пытаетесь накормить %s кого-то %s, но оно исчезает!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -287132,6 +287845,11 @@ msgstr "MOTD" msgid "Create World" msgstr "Создать мир" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "Ошибки? Предложения? Используйте ссылки в MOTD, чтобы сообщить о них." @@ -287404,6 +288122,13 @@ msgstr "Вы уверены, что хотите удалить %s?" msgid "Sorry, something went wrong." msgstr "Извините, что-то пошло не так." +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -291328,6 +292053,15 @@ msgstr[3] "Конфликты" msgid "Mod version" msgstr "Версия мода" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "Путь к моду" @@ -294363,14 +295097,6 @@ msgstr "Порог морали из-за усталости:" msgid "Focus trends towards:" msgstr "Фокус смещается в сторону:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "человек" -msgstr[1] "человека" -msgstr[2] "человек" -msgstr[3] "человек" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -297114,6 +297840,14 @@ msgstr "SDL" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "Сообщения, связанные с SDL, тайлами, наборами тайлов и звуком." +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "Общие" @@ -298317,6 +299051,16 @@ msgstr "Задержка анимации" msgid "The amount of time to pause between animation frames in ms." msgstr "Время паузы между кадрами анимации в мс." +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "Скорость мерцания" @@ -298398,64 +299142,64 @@ msgid "Font height" msgstr "Высота шрифта" #: src/options.cpp -msgid "Set the font height. Requires restart." -msgstr "Установить высоту шрифта. Требуется перезагрузка." +msgid "Set the font height. Requires restart." +msgstr "Выбор высоты шрифта. Требует перезапуска." #: src/options.cpp msgid "Font size" msgstr "Размер шрифта" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "Установить размер шрифта. Требуется перезагрузка." +msgid "Set the font size. Requires restart." +msgstr "Выбор размера шрифта. Требует перезапуска." #: src/options.cpp msgid "Map font width" msgstr "Ширина шрифта карты" #: src/options.cpp -msgid "Set the map font width. Requires restart." -msgstr "Установка ширины шрифта для карты. Требует перезапуск." +msgid "Set the map font width. Requires restart." +msgstr "Выбор ширины шрифта карты. Требует перезапуска." #: src/options.cpp msgid "Map font height" msgstr "Высота шрифта карты" #: src/options.cpp -msgid "Set the map font height. Requires restart." -msgstr "Установка высоты шрифта для карты. Требует перезапуск." +msgid "Set the map font height. Requires restart." +msgstr "Выбор высоты шрифта карты. Требует перезапуска." #: src/options.cpp msgid "Map font size" msgstr "Размер шрифта карты" #: src/options.cpp -msgid "Set the map font size. Requires restart." -msgstr "Установка размера шрифта для карты. Требует перезапуск." +msgid "Set the map font size. Requires restart." +msgstr "Выбор размера шрифта карты. Требует перезапуска." #: src/options.cpp msgid "Overmap font width" msgstr "Ширина шрифта глобальной карты" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." -msgstr "Установка ширины шрифта для глобальной карты. Требует перезапуск." +msgid "Set the overmap font width. Requires restart." +msgstr "Выбор ширины шрифта глобальной карты. Требует перезапуска." #: src/options.cpp msgid "Overmap font height" msgstr "Высота шрифта глобальной карты" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." -msgstr "Установка высоты шрифта для глобальной карты. Требует перезапуск." +msgid "Set the overmap font height. Requires restart." +msgstr "Выбор высоты шрифта глобальной карты. Требует перезапуска." #: src/options.cpp msgid "Overmap font size" msgstr "Размер шрифта глобальной карты" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." -msgstr "Установка размера шрифта для глобальной карты. Требует перезапуск." +msgid "Set the overmap font size. Requires restart." +msgstr "Выбор размера шрифта глобальной карты. Требует перезапуска." #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -306398,6 +307142,11 @@ msgstr "ОТСУТСТВУЮЩИЕ МОДЫ" msgid " [%s]" msgstr "[%s]" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "Н/Д" diff --git a/lang/po/sr.po b/lang/po/sr.po index 5cd5e17358c8..4c77aa3aa7f8 100644 --- a/lang/po/sr.po +++ b/lang/po/sr.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2020 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2020\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Serbian (https://app.transifex.com/bn-team/teams/113585/sr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1490,10 +1490,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3879,10 +3887,25 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -8021,6 +8044,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21926,34 +21960,98 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21962,30 +22060,86 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21994,6 +22148,15 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -22002,6 +22165,14 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -22010,18 +22181,56 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -48525,12 +48734,9 @@ msgstr[2] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Tip 20x66mm municije za Rivtech sačmarice, sa flešet punjenjem. Domaća " -"radinost. Meci bez čaure se ne mogu rastavljati niti ponovo puniti, ni ručno" -" ni mašinski." #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -48542,12 +48748,9 @@ msgstr[2] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Tip 20x66mm municije za Rivtech sačmarice, sa punjenjem sačme. Domaća " -"radinost. Meci bez čaure se ne mogu rastavljati niti ponovo puniti, ni ručno" -" ni mašinski." #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -48560,12 +48763,9 @@ msgstr[2] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" -"Tip 20x66mm municije za Rivtech sačmarice, sa \"tvrdim\" punjenjem. Domaća " -"radinost. Meci bez čaure se ne mogu rastavljati niti ponovo puniti, ni ručno" -" ni mašinski." #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -50200,19 +50400,61 @@ msgstr "" "M3 bestrzajnu pušku. Namenjena uočavanju mete, odnosno destinacije." #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm JHP, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -50584,49 +50826,49 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Jednostepena raketa kalibra 93mm namenjena RPG-7 bacaču." #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -74257,6 +74499,54 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -75415,6 +75705,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -78016,6 +78307,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -84838,6 +85130,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -116884,13 +117177,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -117573,13 +117859,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -127808,7 +128087,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -135612,10 +135892,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -148948,6 +149224,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -148984,6 +149270,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -179311,6 +179611,14 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -189462,6 +189770,14 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -202242,6 +202558,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -202369,6 +202690,27 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -206336,6 +206678,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -206575,6 +206931,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -206582,6 +206939,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -206645,6 +207003,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -206652,6 +207011,7 @@ msgstr[1] "" msgstr[2] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -206854,6 +207214,20 @@ msgstr[0] "" msgstr[1] "" msgstr[2] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -207801,6 +208175,90 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -208966,6 +209424,21 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -210167,6 +210640,13 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -210183,13 +210663,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -213147,10 +213620,24 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -215530,6 +216017,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -215552,6 +216048,79 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -216978,6 +217547,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -217533,6 +218110,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -217691,7 +218288,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -223272,6 +223893,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -228086,6 +228731,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -228202,6 +228851,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -229069,6 +229722,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -241394,6 +242051,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -247264,6 +247926,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -247524,6 +248191,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -251247,6 +251921,15 @@ msgstr[2] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -254205,13 +254888,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -256818,6 +257494,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "" @@ -257890,6 +258574,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -257964,7 +258658,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -257972,7 +258666,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -257980,7 +258674,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -257988,7 +258682,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -257996,7 +258690,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -258004,7 +258698,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -258012,7 +258706,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -258020,7 +258714,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -265586,6 +266280,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/tr.po b/lang/po/tr.po index 2f116d389fce..4f5c54d0fa5b 100644 --- a/lang/po/tr.po +++ b/lang/po/tr.po @@ -1,12 +1,12 @@ # # Translators: -# Coolthulhu , 2020 +# Coolthulhu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" -"Last-Translator: Coolthulhu , 2020\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" +"Last-Translator: Coolthulhu , 2023\n" "Language-Team: Turkish (https://app.transifex.com/bn-team/teams/113585/tr/)\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" @@ -1490,10 +1490,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3856,10 +3864,24 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -7998,6 +8020,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21871,34 +21904,90 @@ msgid_plural "seeing this is a bug" msgstr[0] "" msgstr[1] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -21907,30 +21996,79 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -21939,6 +22077,14 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -21947,6 +22093,13 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -21955,18 +22108,51 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -47534,8 +47720,8 @@ msgstr[1] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47547,8 +47733,8 @@ msgstr[1] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -47561,8 +47747,8 @@ msgstr[1] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49033,18 +49219,57 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -49377,45 +49602,45 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -71437,6 +71662,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -72513,6 +72782,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -74912,6 +75182,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "" @@ -81223,6 +81494,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -111223,12 +111495,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -111866,12 +112132,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -122005,7 +122265,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -129809,10 +130070,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -143142,6 +143399,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -143178,6 +143445,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -172938,6 +173219,13 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -182823,6 +183111,13 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -194813,6 +195108,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -194940,6 +195240,24 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -198777,6 +199095,18 @@ msgid_plural "sledge hammer +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -198982,12 +199312,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -199042,12 +199374,14 @@ msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" msgstr[1] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -199221,6 +199555,18 @@ msgid_plural "dao +2s" msgstr[0] "" msgstr[1] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -200109,6 +200455,78 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -201183,6 +201601,20 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -202258,6 +202690,12 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -202273,12 +202711,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -205104,10 +205536,22 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -207429,6 +207873,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -207451,6 +207904,78 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -208877,6 +209402,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -209432,6 +209965,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -209590,7 +210143,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -215132,6 +215709,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -219933,6 +220534,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -220049,6 +220654,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -220915,6 +221524,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -233211,6 +233824,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -239069,6 +239687,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -239329,6 +239952,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -243040,6 +243670,15 @@ msgstr[1] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -245997,12 +246636,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -248598,6 +249231,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "" @@ -249670,6 +250311,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -249744,7 +250395,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -249752,7 +250403,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -249760,7 +250411,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -249768,7 +250419,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -249776,7 +250427,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -249784,7 +250435,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -249792,7 +250443,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -249800,7 +250451,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -257349,6 +258000,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/uk.po b/lang/po/uk.po index 63ddef341039..8c53820d9fcc 100644 --- a/lang/po/uk.po +++ b/lang/po/uk.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Coolthulhu , 2023\n" "Language-Team: Ukrainian (https://app.transifex.com/bn-team/teams/113585/uk/)\n" "MIME-Version: 1.0\n" @@ -1492,10 +1492,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -2972,10 +2980,10 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "Itchy Metal Thing" msgid_plural "Itchy Metal Things" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Щось металеве що свербить" +msgstr[1] "Щось металеве що свербить" +msgstr[2] "Щось металеве що свербить" +msgstr[3] "Щось металеве що свербить" #. ~ Description for {'str': 'Itchy Metal Thing'} #: data/json/bionics.json @@ -3904,10 +3912,26 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -8048,6 +8072,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21981,34 +22016,106 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -22017,30 +22124,93 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -22049,6 +22219,16 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "зомбі" +msgstr[1] "зомбі" +msgstr[2] "зомбі" +msgstr[3] "зомбі" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -22057,6 +22237,15 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -22065,18 +22254,61 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -26359,10 +26591,10 @@ msgstr "" #: data/mods/Magiclysm/traps.json msgid "bear trap" msgid_plural "bear traps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ведмежий капкан" +msgstr[1] "ведмежих капкани" +msgstr[2] "ведмежих капканів" +msgstr[3] "ведмежий капкан" #. ~ Trap-vehicle collision message for trap 'bear trap' #. ~ Trap-vehicle collision message for trap 'buried bear trap' @@ -29358,10 +29590,10 @@ msgstr "" #: data/json/items/tool/cooking.json data/json/vehicleparts/vehicle_parts.json msgid "water purifier" msgid_plural "water purifiers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "водоочисник" +msgstr[1] "водоочисника" +msgstr[2] "водоочисників" +msgstr[3] "водоочисник" #. ~ Description for water purifier #: data/json/furniture_and_terrain/furniture-plumbing.json @@ -30992,10 +31224,10 @@ msgstr "" #: data/json/items/tool/deployable.json msgid "metal butchering rack" msgid_plural "metal butchering racks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "металева стійка для патрання/розбирання" +msgstr[1] "металеві стійки для патрання/розбирання" +msgstr[2] "металевих стійок для патрання/розбирання" +msgstr[3] "металева стійка для патрання/розбирання" #. ~ Description for metal butchering rack #: data/json/furniture_and_terrain/furniture-tools.json @@ -36830,10 +37062,10 @@ msgstr "" #: data/json/items/ammo.json data/mods/Aftershock/items/item_overrides.json msgid "battery" msgid_plural "batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "батарейка" +msgstr[1] "батарейки" +msgstr[2] "батарейки" +msgstr[3] "батарейки" #. ~ Description for {'str': 'battery', 'str_pl': 'batteries'} #: data/json/items/ammo.json @@ -36899,10 +37131,10 @@ msgstr "ЯКЩО ВИ ЦЕ БАЧИТЕ, ТО ЦЕ ПРОГРАМНА ПОМИЛ #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "thread" msgid_plural "thread" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "нитка" +msgstr[1] "нитки" +msgstr[2] "нитки" +msgstr[3] "нитки" #. ~ Description for {'str_sp': 'thread'} #: data/json/items/ammo.json @@ -36940,10 +37172,10 @@ msgstr "Міцні тонкі рослинні волокна, можуть сл #: data/json/items/ammo.json msgid "yarn" msgid_plural "yarn" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пряжа" +msgstr[1] " пряжа" +msgstr[2] "пряжа" +msgstr[3] "пряжа" #. ~ Description for {'str_sp': 'yarn'} #: data/json/items/ammo.json @@ -37043,10 +37275,10 @@ msgstr "" #: data/json/items/ammo.json msgid "watery plutonium slurry" msgid_plural "watery plutonium slurry" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "водяниста плутонієва суспензія" +msgstr[1] "водяниста плутонієва суспензія" +msgstr[2] "водяниста плутонієва суспензія" +msgstr[3] "водяниста плутонієва суспензія" #: data/json/items/ammo.json data/json/snippets/music.json msgid "rock" @@ -37115,10 +37347,10 @@ msgstr "" #: data/json/items/ammo.json msgid "bearings" msgid_plural "bearings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "підшипник" +msgstr[1] "підшипники" +msgstr[2] "підшипники" +msgstr[3] "підшипники" #. ~ Description for {'str_sp': 'bearings'} #: data/json/items/ammo.json @@ -37655,10 +37887,10 @@ msgstr "" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "tinder" msgid_plural "tinder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "трут" +msgstr[1] "трута" +msgstr[2] "трута" +msgstr[3] "трут" #. ~ Description for {'str_sp': 'tinder'} #: data/json/items/ammo.json @@ -37928,10 +38160,10 @@ msgstr "" #: data/json/items/ammo_types.json data/json/items/fuel.json msgid "gasoline" msgid_plural "gasoline" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бензин" +msgstr[1] "бензин" +msgstr[2] "бензин" +msgstr[3] "бензин" #: data/json/items/ammo_types.json msgid "jp8" @@ -37944,18 +38176,18 @@ msgstr "" #: data/json/items/ammo_types.json data/json/items/fuel.json msgid "diesel" msgid_plural "diesel" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дизель" +msgstr[1] "дизель" +msgstr[2] "дизель" +msgstr[3] "дизель" #: data/json/items/ammo_types.json data/json/items/fuel.json msgid "lamp oil" msgid_plural "lamp oil" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "лампова олія" +msgstr[1] "лампової олія" +msgstr[2] "лампова олія" +msgstr[3] "лампова олія" #: data/json/items/ammo_types.json data/json/items/fuel.json msgid "motor oil" @@ -38046,10 +38278,10 @@ msgstr "" #: data/mods/Aftershock/items/tools.json msgid "UPS" msgid_plural "UPS's" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "УДЖ" +msgstr[1] "УДЖ" +msgstr[2] "УДЖ" +msgstr[3] "УДЖ" #: data/json/items/ammo_types.json msgid "throwing weapon" @@ -38184,10 +38416,10 @@ msgstr[3] "" #: data/json/items/ammo_types.json data/json/items/comestibles/drink.json msgid "water" msgid_plural "water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "вода" +msgstr[1] "води" +msgstr[2] "води" +msgstr[3] "вода" #: data/json/items/ammo_types.json msgid "acid" @@ -38289,10 +38521,10 @@ msgstr "" #: data/json/items/battery.json msgid "ultra-light battery" msgid_plural "ultra-light batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ультралегка батарейка" +msgstr[1] "ультралегкі батарейки" +msgstr[2] "ультралегких батарейок" +msgstr[3] "ультралегка батарейка" #. ~ Description for {'str': 'ultra-light battery', 'str_pl': 'ultra-light #. batteries'} @@ -38340,10 +38572,10 @@ msgstr "" #: data/json/items/battery.json msgid "light battery" msgid_plural "light batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "легка батарейка" +msgstr[1] "легкі батарейки" +msgstr[2] "легких батарейок" +msgstr[3] "легка батарейка" #. ~ Description for {'str': 'light battery', 'str_pl': 'light batteries'} #: data/json/items/battery.json @@ -38355,10 +38587,10 @@ msgstr "" #: data/json/items/battery.json msgid "light battery (high-capacity)" msgid_plural "light batteries (high-capacity)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "легка батарейка (підвищ. ємності)" +msgstr[1] "легкі батарейки (підвищ. ємності)" +msgstr[2] "легких батарейок (підвищ. ємності)" +msgstr[3] "легка батарейка (підвищ. ємності)" #. ~ Description for {'str': 'light battery (high-capacity)', 'str_pl': 'light #. batteries (high-capacity)'} @@ -38406,10 +38638,10 @@ msgstr "" #: data/json/items/battery.json msgid "medium battery" msgid_plural "medium batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "середня батарея" +msgstr[1] "середні батареї" +msgstr[2] "середніх батарей" +msgstr[3] "середня батарея" #. ~ Description for {'str': 'medium battery', 'str_pl': 'medium batteries'} #: data/json/items/battery.json @@ -38421,10 +38653,10 @@ msgstr "" #: data/json/items/battery.json msgid "medium battery (high-capacity)" msgid_plural "medium batteries (high-capacity)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "середня батарея (підвищ. ємності)" +msgstr[1] "середні батареї (підвищ. ємності)" +msgstr[2] "середніх батарей (підвищ. ємності)" +msgstr[3] "середня батарея (підвищ. ємності)" #. ~ Description for {'str': 'medium battery (high-capacity)', 'str_pl': #. 'medium batteries (high-capacity)'} @@ -38472,10 +38704,10 @@ msgstr "" #: data/json/items/battery.json msgid "heavy battery" msgid_plural "heavy batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "важка батарея" +msgstr[1] "важких батареї" +msgstr[2] "важких батарей" +msgstr[3] "важка батарея" #. ~ Description for {'str': 'heavy battery', 'str_pl': 'heavy batteries'} #: data/json/items/battery.json @@ -40372,10 +40604,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "sulfur" msgid_plural "sulfur" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сірка" +msgstr[1] "сірка" +msgstr[2] "сірка" +msgstr[3] "сірка" #. ~ Description for {'str_sp': 'sulfur'} #: data/json/items/chemicals_and_resources.json @@ -40389,10 +40621,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "chunk of sulfur" msgid_plural "chunks of sulfur" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "глиба сірки" +msgstr[1] "глиби сірки" +msgstr[2] "глиби сірки" +msgstr[3] "глиби сірки" #. ~ Description for {'str': 'chunk of sulfur', 'str_pl': 'chunks of sulfur'} #: data/json/items/chemicals_and_resources.json @@ -40458,10 +40690,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "soil" msgid_plural "soil" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ґрунт" +msgstr[1] "ґрунту" +msgstr[2] "ґрунту" +msgstr[3] "ґрунт" #. ~ Description for {'str_sp': 'soil'} #: data/json/items/chemicals_and_resources.json @@ -40488,10 +40720,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "rock salt" msgid_plural "rock salt" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кам'яна сіль" +msgstr[1] "кам'яна сіль" +msgstr[2] "кам'яна сіль" +msgstr[3] "кам'яна сіль" #. ~ Description for {'str_sp': 'rock salt'} #: data/json/items/chemicals_and_resources.json @@ -40531,10 +40763,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "bleach" msgid_plural "bleach" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "хлорка" +msgstr[1] "хлорки" +msgstr[2] "хлорки" +msgstr[3] "хлорка" #. ~ Description for {'str_sp': 'bleach'} #: data/json/items/chemicals_and_resources.json @@ -40546,10 +40778,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "ammonia" msgid_plural "ammonia" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "нашатирний спирт" +msgstr[1] "нашатирного спирту" +msgstr[2] "нашатирного спирту" +msgstr[3] "нашатирний спирт" #. ~ Description for {'str_sp': 'ammonia'} #: data/json/items/chemicals_and_resources.json @@ -40620,10 +40852,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "salt water" msgid_plural "salt water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "солона вода" +msgstr[1] "солоної води" +msgstr[2] "солоної води" +msgstr[3] "солона вода" #. ~ Description for {'str_sp': 'salt water'} #: data/json/items/chemicals_and_resources.json @@ -40646,10 +40878,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "acid water" msgid_plural "acid water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кислотна вода" +msgstr[1] "кислотної води" +msgstr[2] "кислотної води" +msgstr[3] "кислотна вода" #. ~ Description for {'str_sp': 'acid water'} #: data/json/items/chemicals_and_resources.json @@ -40661,10 +40893,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "weak acid water" msgid_plural "weak acid water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "слабкокисла вода" +msgstr[1] "слабкокислої води" +msgstr[2] "слабкокислої води" +msgstr[3] "слабкокисла вода" #. ~ Description for {'str_sp': 'weak acid water'} #: data/json/items/chemicals_and_resources.json @@ -40783,10 +41015,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "sulfuric acid" msgid_plural "sulfuric acid" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сірчана кислота" +msgstr[1] "сірчана кислота" +msgstr[2] "сірчана кислота" +msgstr[3] "сірчана кислота" #. ~ Description for {'str_sp': 'sulfuric acid'} #: data/json/items/chemicals_and_resources.json @@ -40902,10 +41134,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "ammonium nitrate" msgid_plural "ammonium nitrate" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Нітрат амонію" +msgstr[1] "Нітрату амонію" +msgstr[2] "Нітрату амонію" +msgstr[3] "Нітрат амонію" #. ~ Description for {'str_sp': 'ammonium nitrate'} #: data/json/items/chemicals_and_resources.json @@ -41054,10 +41286,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "black gunpowder" msgid_plural "black gunpowder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "чорний зброярський порох" +msgstr[1] "чорний зброярський порох" +msgstr[2] "чорний зброярський порох" +msgstr[3] "чорний зброярський порох" #. ~ Description for {'str_sp': 'black gunpowder'} #: data/json/items/chemicals_and_resources.json @@ -41185,10 +41417,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "sewage water" msgid_plural "sewage water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "стічні води" +msgstr[1] "стічних вод" +msgstr[2] "стічних вод" +msgstr[3] "стічні води" #. ~ Description for {'str_sp': 'sewage water'} #: data/json/items/chemicals_and_resources.json @@ -41255,10 +41487,10 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "wood ash" msgid_plural "wood ashes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "деревний попіл" +msgstr[1] "деревний попіл" +msgstr[2] "деревний попіл" +msgstr[3] "деревний попіл" #. ~ Description for {'str': 'wood ash', 'str_pl': 'wood ashes'} #: data/json/items/chemicals_and_resources.json @@ -41521,10 +41753,10 @@ msgstr "" #: data/json/items/containers.json data/json/vehicleparts/tanks.json msgid "steel drum (100L)" msgid_plural "steel drums (100L)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сталева діжка (100 л)" +msgstr[1] "сталеві діжки (100 л)" +msgstr[2] "сталевих діжок (100 л)" +msgstr[3] "сталева діжка (100 л)" #. ~ Description for {'str': 'steel drum (100L)', 'str_pl': 'steel drums #. (100L)'} @@ -41535,10 +41767,10 @@ msgstr "" #: data/json/items/containers.json data/json/vehicleparts/tanks.json msgid "steel drum (200L)" msgid_plural "steel drums (200L)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сталева діжка (200 л)" +msgstr[1] "сталеві діжки (200 л)" +msgstr[2] "сталевих діжок (200 л)" +msgstr[3] "сталева діжка (200 л)" #. ~ Description for {'str': 'steel drum (200L)', 'str_pl': 'steel drums #. (200L)'} @@ -41576,10 +41808,10 @@ msgstr "" #: data/json/items/containers.json msgid "plastic bag" msgid_plural "plastic bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пакетик" +msgstr[1] "пакетик" +msgstr[2] "пакетики" +msgstr[3] "пакетик" #. ~ Description for {'str': 'plastic bag'} #: data/json/items/containers.json @@ -41633,10 +41865,10 @@ msgstr "" #: data/json/items/containers.json msgid "glass bottle" msgid_plural "glass bottles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "скляна пляшка" +msgstr[1] "скляна пляшка" +msgstr[2] "скляна пляшка" +msgstr[3] "скляні пляшки" #. ~ Description for {'str': 'glass bottle'} #: data/json/items/containers.json @@ -41646,10 +41878,10 @@ msgstr "Скляна пляшка, що закривається, вміщує 7 #: data/json/items/containers.json msgid "plastic bottle" msgid_plural "plastic bottles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластикова пляшка" +msgstr[1] "пластикова пляшка" +msgstr[2] "пластикова пляшка" +msgstr[3] "пластикові пляшки" #. ~ Description for {'str': 'plastic bottle'} #: data/json/items/containers.json @@ -41679,10 +41911,10 @@ msgstr "" #: data/json/items/containers.json msgid "small plastic bottle" msgid_plural "small plastic bottles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мала пластикова пляшка" +msgstr[1] "мала пластикова пляшка" +msgstr[2] "мала пластикова пляшка" +msgstr[3] "малі пластикові пляшки" #. ~ Description for {'str': 'small plastic bottle'} #: data/json/items/containers.json @@ -41692,10 +41924,10 @@ msgstr "Пластикова пляшка, що закривається, вмі #: data/json/items/containers.json msgid "large plastic bottle" msgid_plural "large plastic bottles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "велика пластикова пляшка" +msgstr[1] "велика пластикова пляшка" +msgstr[2] "велика пластикова пляшка" +msgstr[3] "великі пластикові пляшки" #. ~ Description for {'str': 'large plastic bottle'} #: data/json/items/containers.json @@ -41709,10 +41941,10 @@ msgstr "" #: data/json/items/containers.json msgid "clay bowl" msgid_plural "clay bowls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "глиняна миска" +msgstr[1] "глиняні миски" +msgstr[2] "глиняних мисок" +msgstr[3] "глиняна миска" #. ~ Description for {'str': 'clay bowl'} #: data/json/items/containers.json @@ -41739,10 +41971,10 @@ msgstr "" #: data/json/items/containers.json msgid "small cardboard box" msgid_plural "small cardboard boxes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "невелика картона коробка" +msgstr[1] "невеликі картоні коробки" +msgstr[2] "невеликих картоних коробок" +msgstr[3] "невелика картона коробка" #. ~ Description for {'str': 'small cardboard box', 'str_pl': 'small cardboard #. boxes'} @@ -41753,10 +41985,10 @@ msgstr "Невелика картона коробка. Розміром не б #: data/json/items/containers.json msgid "cardboard box" msgid_plural "cardboard boxes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "картонна коробка" +msgstr[1] "картонна коробка" +msgstr[2] "картонна коробка" +msgstr[3] "картонні коробки" #. ~ Description for {'str': 'cardboard box', 'str_pl': 'cardboard boxes'} #: data/json/items/containers.json @@ -41792,10 +42024,10 @@ msgstr "" #: data/json/items/containers.json msgid "hydration pack" msgid_plural "hydration packs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "питний рюкзак" +msgstr[1] "питні рюкзаки" +msgstr[2] "питних рюкзаків" +msgstr[3] "питний рюкзак" #. ~ Description for {'str': 'hydration pack'} #: data/json/items/containers.json @@ -41808,10 +42040,10 @@ msgstr "" #: data/json/items/containers.json msgid "aluminum can" msgid_plural "aluminum cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "алюмінієва банка" +msgstr[1] "алюмінієві банки" +msgstr[2] "алюмінієвих банок" +msgstr[3] "алюмінієва банка" #. ~ Description for {'str': 'aluminum can'} #: data/json/items/containers.json @@ -41821,10 +42053,10 @@ msgstr "" #: data/json/items/containers.json msgid "opened aluminum can" msgid_plural "opened aluminum cans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "відкрита алюмінієва банка" +msgstr[1] "відкритих алюмінієвих банки" +msgstr[2] "відкритих алюмінієвих банок" +msgstr[3] "відкрита алюмінієва банка" #. ~ Description for {'str': 'opened aluminum can'} #: data/json/items/containers.json @@ -41935,10 +42167,10 @@ msgstr "" #: data/json/items/containers.json msgid "plastic canteen" msgid_plural "plastic canteens" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластикова фляга" +msgstr[1] "пластикові фляги" +msgstr[2] "пластикових фляг" +msgstr[3] "пластикова фляга" #. ~ Description for {'str': 'plastic canteen'} #: data/json/items/containers.json @@ -41950,10 +42182,10 @@ msgstr "" #: data/json/items/containers.json msgid "thermos" msgid_plural "thermoses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "термос" +msgstr[1] "термос" +msgstr[2] "термос" +msgstr[3] "термоси" #. ~ Description for {'str': 'thermos', 'str_pl': 'thermoses'} #: data/json/items/containers.json @@ -42010,10 +42242,10 @@ msgstr "" #: data/json/items/containers.json msgid "plastic cup" msgid_plural "plastic cups" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластиковий стаканчик" +msgstr[1] "пластикових стаканчика" +msgstr[2] "пластикових стаканчиків" +msgstr[3] "пластиковий стаканчик" #. ~ Description for {'str': 'plastic cup'} #: data/json/items/containers.json @@ -42023,10 +42255,10 @@ msgstr "" #: data/json/items/containers.json msgid "opened plastic cup" msgid_plural "opened plastic cups" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "відкритий пластиковий стаканчик" +msgstr[1] "відкритих пластикових стаканчика" +msgstr[2] "відкритих пластикових стаканчиків" +msgstr[3] "відкритий пластиковий стаканчик" #. ~ Description for {'str': 'opened plastic cup'} #: data/json/items/containers.json @@ -42036,10 +42268,10 @@ msgstr "" #: data/json/items/containers.json msgid "glass flask" msgid_plural "glass flasks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "скляна колба" +msgstr[1] "скляні колби" +msgstr[2] "скляних колб" +msgstr[3] "скляна колба" #. ~ Description for {'str': 'glass flask'} #: data/json/items/containers.json @@ -42049,10 +42281,10 @@ msgstr "" #: data/json/items/containers.json msgid "test tube" msgid_plural "test tubes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пробірка" +msgstr[1] "пробірки" +msgstr[2] "пробірок" +msgstr[3] "пробірка" #. ~ Description for {'str': 'test tube'} #: data/json/items/containers.json @@ -42108,10 +42340,10 @@ msgstr "" #: data/json/items/containers.json msgid "hip flask" msgid_plural "hip flasks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "фляжка" +msgstr[1] "фляжки" +msgstr[2] "фляжок" +msgstr[3] "фляжка" #. ~ Description for {'str': 'hip flask'} #: data/json/items/containers.json @@ -42123,10 +42355,10 @@ msgstr "" #: data/json/items/containers.json msgid "3L glass jar" msgid_plural "3L glass jars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "3-л скляна банка" +msgstr[1] "3-л скляні банки" +msgstr[2] "3-л скляних банок" +msgstr[3] "3-л скляна банка" #. ~ Description for {'str': '3L glass jar'} #: data/json/items/containers.json @@ -42136,10 +42368,10 @@ msgstr "" #: data/json/items/containers.json msgid "sealed 3L glass jar" msgid_plural "sealed 3L glass jars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "закатана 3-л скляна банка" +msgstr[1] "закатані 3-л скляні банки" +msgstr[2] "закатаних 3-л скляних банок" +msgstr[3] "закатана 3-л скляна банка" #. ~ Description for {'str': 'sealed 3L glass jar'} #: data/json/items/containers.json @@ -42151,10 +42383,10 @@ msgstr "" #: data/json/items/containers.json msgid "glass jar" msgid_plural "glass jars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "скляна банка" +msgstr[1] "скляні банки" +msgstr[2] "скляних банок" +msgstr[3] "скляна банка" #. ~ Description for {'str': 'glass jar'} #: data/json/items/containers.json @@ -42164,10 +42396,10 @@ msgstr "" #: data/json/items/containers.json msgid "sealed glass jar" msgid_plural "sealed glass jars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "закатана скляна банка" +msgstr[1] "закатані скляні банки" +msgstr[2] "закатаних скляних банок" +msgstr[3] "закатана скляна банка" #. ~ Description for {'str': 'sealed glass jar'} #: data/json/items/containers.json @@ -42180,10 +42412,10 @@ msgstr "" #: data/json/items/containers.json msgid "plastic jerrycan" msgid_plural "plastic jerrycans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластикова каністра" +msgstr[1] "пластикові каністри" +msgstr[2] "пластикових каністр" +msgstr[3] "пластикова каністра" #. ~ Description for {'str': 'plastic jerrycan'} #: data/json/items/containers.json @@ -42195,10 +42427,10 @@ msgstr "" #: data/json/items/containers.json msgid "steel jerrycan" msgid_plural "steel jerrycans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сталева каністра" +msgstr[1] "сталеві каністри" +msgstr[2] "сталевих каністр" +msgstr[3] "сталева каністра" #. ~ Description for {'str': 'steel jerrycan'} #: data/json/items/containers.json @@ -42223,10 +42455,10 @@ msgstr "" #: data/json/items/containers.json msgid "gallon jug" msgid_plural "gallon jugs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "1-галонний бутиль" +msgstr[1] "1-галонних бутля" +msgstr[2] "1-галонних бутлів" +msgstr[3] "1-галонний бутиль" #. ~ Description for {'str': 'gallon jug'} #: data/json/items/containers.json @@ -42236,10 +42468,10 @@ msgstr "" #: data/json/items/containers.json msgid "aluminum keg" msgid_plural "aluminum kegs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "алюмінієве барильце" +msgstr[1] "алюмінієвих барильця" +msgstr[2] "алюмінієвих барилець" +msgstr[3] "алюмінієве барильце" #. ~ Description for {'str': 'aluminum keg'} #: data/json/items/containers.json @@ -42281,10 +42513,10 @@ msgstr "" #: data/json/items/containers.json msgid "metal tank (60L)" msgid_plural "metal tanks (60L)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "металевий бак (60 л)" +msgstr[1] "металеві баки (60 л)" +msgstr[2] "металевих баків (60 л)" +msgstr[3] "металевий бак (60 л)" #. ~ Description for {'str': 'metal tank (60L)', 'str_pl': 'metal tanks #. (60L)'} @@ -42397,10 +42629,10 @@ msgstr "" #: data/json/items/containers.json msgid "paper wrapper" msgid_plural "paper wrappers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "обгортковий папір" +msgstr[1] "обгортковий папір" +msgstr[2] "обгортковий папір" +msgstr[3] "обгортковий папір" #. ~ Description for {'str': 'paper wrapper'} #: data/json/items/containers.json @@ -42423,10 +42655,10 @@ msgstr "" #: data/json/items/containers.json msgid "plastic tub" msgid_plural "plastic tubs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластикове відерце" +msgstr[1] "пластикових відерця" +msgstr[2] "пластикових відерець" +msgstr[3] "пластикове відерце" #. ~ Description for {'str': 'plastic tub'} #: data/json/items/containers.json @@ -42846,10 +43078,10 @@ msgstr "" #: data/json/items/fuel.json msgid "biodiesel" msgid_plural "biodiesel" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "біодизель" +msgstr[1] "біодизель" +msgstr[2] "біодизель" +msgstr[3] "біодизель" #. ~ Description for {'str_sp': 'biodiesel'} #: data/json/items/fuel.json @@ -43102,10 +43334,10 @@ msgstr "" #: data/json/items/generic.json msgid "withered plant" msgid_plural "withered plants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зів'яла рослина" +msgstr[1] "зів'ялі рослини" +msgstr[2] "зів'ялих рослин" +msgstr[3] "зів'яла рослина" #. ~ Description for {'str': 'withered plant'} #: data/json/items/generic.json @@ -43224,10 +43456,10 @@ msgstr "" #: data/json/items/generic.json msgid "steel chain" msgid_plural "steel chains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сталевий ланцюг" +msgstr[1] "сталевих ланцюга" +msgstr[2] "сталевих ланцюгів" +msgstr[3] "сталевий ланцюг" #. ~ Description for {'str': 'steel chain'} #: data/json/items/generic.json @@ -43239,10 +43471,10 @@ msgstr "" #: data/json/items/generic.json msgid "chunk of chitin" msgid_plural "chunks of chitin" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шматок хітину" +msgstr[1] "шматки хітину" +msgstr[2] "шматків хітину" +msgstr[3] "шматок хітину" #. ~ Description for {'str': 'chunk of chitin', 'str_pl': 'chunks of chitin'} #: data/json/items/generic.json @@ -43268,10 +43500,10 @@ msgstr "" #: data/json/items/generic.json msgid "chunk of biosilicified chitin" msgid_plural "chunks of biosilicified chitin" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шматок біосиліфікованого хітину" +msgstr[1] "шматки біосиліфікованого хітину" +msgstr[2] "шматків біосиліфікованого хітину" +msgstr[3] "шматок біосиліфікованого хітину" #. ~ Description for {'str': 'chunk of biosilicified chitin', 'str_pl': #. 'chunks of biosilicified chitin'} @@ -43608,10 +43840,10 @@ msgstr "" #: data/json/items/generic.json msgid "burnt out torch" msgid_plural "burnt out torches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "згорілий смолоскип" +msgstr[1] "згорілих смолоскипа" +msgstr[2] "згорілих смолоскипів" +msgstr[3] "згорілий смолоскип" #. ~ Description for {'str': 'burnt out torch', 'str_pl': 'burnt out torches'} #: data/json/items/generic.json @@ -43623,10 +43855,10 @@ msgstr "" #: data/json/items/generic.json msgid "dead flare" msgid_plural "dead flares" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "згасла освітлювальна ракета" +msgstr[1] "згаслі освітлювальні ракети" +msgstr[2] "згаслих освітлювальних ракет" +msgstr[3] "згасла освітлювальна ракета" #. ~ Description for {'str': 'dead flare'} #: data/json/items/generic.json @@ -44318,10 +44550,10 @@ msgstr "" #: data/json/items/generic.json msgid "burnt out bionic" msgid_plural "burnt out bionics" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "перегоріла біоніка" +msgstr[1] "перегорілих біоніки" +msgstr[2] "перегорілих біонік" +msgstr[3] "перегоріла біоніка" #. ~ Description for {'str': 'burnt out bionic'} #: data/json/items/generic.json @@ -44483,10 +44715,10 @@ msgstr "" #: data/json/items/generic.json msgid "blood soaked rag" msgid_plural "blood soaked rags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ганчірка, що просякнута кров'ю" +msgstr[1] "ганчірки, що просякнуті кров'ю" +msgstr[2] "ганчірок, що просякнуті кров'ю" +msgstr[3] "ганчірка, що просякнута кров'ю" #. ~ Description for {'str': 'blood soaked rag'} #: data/json/items/generic.json @@ -45085,10 +45317,10 @@ msgstr "" #: data/json/items/generic.json msgid "pillow" msgid_plural "pillows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "подушка" +msgstr[1] "подушки" +msgstr[2] "подушок" +msgstr[3] "подушка" #. ~ Description for {'str': 'pillow'} #: data/json/items/generic.json @@ -45233,10 +45465,10 @@ msgstr "" #: data/json/items/generic.json data/json/items/comestibles/med.json msgid "cigarette" msgid_plural "cigarettes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "цигарка" +msgstr[1] "цигарки" +msgstr[2] "цигарок" +msgstr[3] "цигарка" #. ~ Use action msg for {'str': 'cigarette'}. #: data/json/items/generic.json @@ -45253,10 +45485,10 @@ msgstr "" #: data/json/items/generic.json msgid "cigarette butt" msgid_plural "cigarette butts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "недопалок" +msgstr[1] "недопалки" +msgstr[2] "недопалків" +msgstr[3] "недопалок" #. ~ Description for {'str': 'cigarette butt'} #: data/json/items/generic.json @@ -45334,10 +45566,10 @@ msgstr "" #: data/json/items/generic.json msgid "cash card" msgid_plural "cash cards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кредитка" +msgstr[1] "кредитка" +msgstr[2] "кредитки" +msgstr[3] "кредитка" #. ~ Description for {'str': 'cash card'} #: data/json/items/generic.json @@ -45552,10 +45784,10 @@ msgstr "" #: data/json/items/generic.json msgid "plastic flower pot" msgid_plural "plastic flower pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластиковий квітковий горщик" +msgstr[1] "пластикових квіткових горщика" +msgstr[2] "пластикових квіткових горщиків" +msgstr[3] "пластиковий квітковий горщик" #. ~ Description for {'str': 'plastic flower pot'} #: data/json/items/generic.json @@ -46005,10 +46237,10 @@ msgstr "" #: data/json/items/newspaper.json msgid "flyer" msgid_plural "flyers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "рекламна листівка" +msgstr[1] "рекламні листівки" +msgstr[2] "рекламних листівок" +msgstr[3] "рекламна листівка" #. ~ Description for {'str': 'flyer'} #: data/json/items/newspaper.json @@ -46046,10 +46278,10 @@ msgstr "" #: data/json/items/newspaper.json msgid "newspaper page" msgid_plural "newspaper pages" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сторінка газети" +msgstr[1] "сторінку газети" +msgstr[2] "сторінки газет" +msgstr[3] "сторінки газет" #. ~ Description for {'str': 'newspaper page'} #: data/json/items/newspaper.json @@ -47042,10 +47274,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "pair of ear plugs" msgid_plural "pairs of ear plugs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "беруші" +msgstr[1] "беруші" +msgstr[2] "беруші" +msgstr[3] "беруш" #. ~ Description for {'str': 'pair of ear plugs', 'str_pl': 'pairs of ear #. plugs'} @@ -47297,10 +47529,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "fedora" msgid_plural "fedoras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "капелюх" +msgstr[1] "капелюхи" +msgstr[2] "капелюхів" +msgstr[3] "капелюх" #. ~ Use action menu_text for {'str': 'fedora'}. #. ~ Use action menu_text for {'str': 'straw fedora'}. @@ -47326,10 +47558,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "pair of thermal electric socks" msgid_plural "pairs of thermal electric socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара теплових електрошкарпеток" +msgstr[1] "пари теплових електрошкарпеток" +msgstr[2] "пар теплових електрошкарпеток" +msgstr[3] "пара теплових електрошкарпеток" #. ~ Use action msg for {'str': 'pair of thermal electric socks', 'str_pl': #. 'pairs of thermal electric socks'}. @@ -47382,10 +47614,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "pair of thermal electric socks (on)" msgid_plural "pairs of thermal electric socks (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара теплових електрошкарпеток (увімк)" +msgstr[1] "пар теплових електрошкарпеток (увімк)" +msgstr[2] "пар теплових електрошкарпеток (увімк)" +msgstr[3] "пара теплових електрошкарпеток (увімк)" #. ~ Use action msg for {'str': 'pair of thermal electric socks (on)', #. 'str_pl': 'pairs of thermal electric socks (on)'}. @@ -47524,10 +47756,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "pair of binoculars" msgid_plural "pairs of binoculars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бінокль" +msgstr[1] "біноклі" +msgstr[2] "біноклів" +msgstr[3] "бінокль" #. ~ Description for {'str': 'pair of binoculars', 'str_pl': 'pairs of #. binoculars'} @@ -47542,10 +47774,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "headlamp" msgid_plural "headlamps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "налобний ліхтар" +msgstr[1] "налобних ліхтаря" +msgstr[2] "налобних ліхтарів" +msgstr[3] "налобний ліхтар" #. ~ Use action msg for {'str': 'headlamp'}. #: data/json/items/tool_armor.json @@ -47567,10 +47799,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "headlamp (on)" msgid_plural "headlamps (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "налобний ліхтар (увімк)" +msgstr[1] "налобних ліхтаря (увімк)" +msgstr[2] "налобних ліхтарів (увімк)" +msgstr[3] "налобний ліхтар (увімк)" #. ~ Description for {'str': 'headlamp (on)', 'str_pl': 'headlamps (on)'} #: data/json/items/tool_armor.json @@ -47583,10 +47815,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "survivor headlamp" msgid_plural "survivor headlamps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "налобний ліхтар виживальника" +msgstr[1] "налобних ліхтаря виживальника" +msgstr[2] "налобних ліхтарів виживальника" +msgstr[3] "налобний ліхтар виживальника" #. ~ Use action msg for {'str': 'survivor headlamp'}. #: data/json/items/tool_armor.json @@ -47610,10 +47842,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "survivor headlamp (on)" msgid_plural "survivor headlamps (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "налобний ліхтар виживальника (увімк)" +msgstr[1] "налобних ліхтаря виживальника (увімк)" +msgstr[2] "налобних ліхтарів виживальника (увімк)" +msgstr[3] "налобний ліхтар виживальника (увімк)" #. ~ Description for {'str': 'survivor headlamp (on)', 'str_pl': 'survivor #. headlamps (on)'} @@ -47923,10 +48155,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "gas mask" msgid_plural "gas masks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "протигаз" +msgstr[1] "протигаз" +msgstr[2] "протигаз" +msgstr[3] "протигази" #. ~ Description for {'str': 'gas mask'} #: data/json/items/tool_armor.json @@ -48116,10 +48348,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "pair of light amp goggles" msgid_plural "pairs of light amp goggles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "окуляри нічного бачення" +msgstr[1] "окулярів нічного бачення" +msgstr[2] "окулярів нічного бачення" +msgstr[3] "окуляри нічного бачення" #. ~ Description for {'str': 'pair of light amp goggles', 'str_pl': 'pairs of #. light amp goggles'} @@ -48332,10 +48564,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "radiation biomonitor" msgid_plural "radiation biomonitors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "біомонітор радіації" +msgstr[1] "біомонітори радіації" +msgstr[2] "біомоніторів радіації" +msgstr[3] "біомонітор радіації" #. ~ Description for {'str': 'radiation biomonitor'} #: data/json/items/tool_armor.json @@ -48426,10 +48658,10 @@ msgstr "" #: data/json/items/tool_armor.json src/iuse.cpp msgid "towel" msgid_plural "towels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "рушник" +msgstr[1] "рушника" +msgstr[2] "рушників" +msgstr[3] "рушники" #. ~ Description for {'str': 'towel'} #: data/json/items/tool_armor.json @@ -48456,10 +48688,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "soiled towel" msgid_plural "soiled towels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "забруднений рушник" +msgstr[1] "забруднений рушник" +msgstr[2] "забруднений рушник" +msgstr[3] "забруднені рушники" #. ~ Description for {'str': 'soiled towel'} #: data/json/items/tool_armor.json @@ -48473,10 +48705,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "straw fedora" msgid_plural "straw fedoras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "солом'яний бриль" +msgstr[1] "солом'яних бриля" +msgstr[2] "солом'яних брилів" +msgstr[3] "солом'яний бриль" #. ~ Description for {'str': 'straw fedora'} #: data/json/items/tool_armor.json @@ -48627,10 +48859,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "knit scarf" msgid_plural "knit scarves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "в'язаний шарф" +msgstr[1] "в'язані шарфи" +msgstr[2] "в'язаних шарфів" +msgstr[3] "в'язаний шарф" #. ~ Description for {'str': 'knit scarf', 'str_pl': 'knit scarves'} #: data/json/items/tool_armor.json @@ -48642,10 +48874,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "knit scarf (loose)" msgid_plural "knit scarves (loose)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "в'язаний шарф (незав'язаний)" +msgstr[1] "в'язані шарфи (незав'язані)" +msgstr[2] "в'язаних шарфів (незав'язаних)" +msgstr[3] "в'язаний шарф (незав'язаний)" #. ~ Description for {'str': 'knit scarf (loose)', 'str_pl': 'knit scarves #. (loose)'} @@ -48901,10 +49133,10 @@ msgstr "" #: data/json/items/tool_armor.json msgid "whistle" msgid_plural "whistles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "свисток" +msgstr[1] "свистка" +msgstr[2] "свистків" +msgstr[3] "свисток" #. ~ Use action noise_message for {'str': 'whistle'}. #. ~ Use action noise_message for {'str': 'whistle multitool'}. @@ -49490,8 +49722,8 @@ msgstr[3] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49505,8 +49737,8 @@ msgstr[3] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49521,8 +49753,8 @@ msgstr[3] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -51238,20 +51470,65 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -51636,53 +51913,53 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Одноступінчатий фугасний реактивний 93мм постріл для РПГ-7" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -52216,10 +52493,10 @@ msgstr "" #: data/json/items/armor/ammo_pouch.json data/mods/Magiclysm/items/armor.json msgid "quiver" msgid_plural "quivers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "колчан" +msgstr[1] "колчан" +msgstr[2] "колчанів" +msgstr[3] "колчан" #. ~ Description for {'str': 'quiver'} #: data/json/items/armor/ammo_pouch.json @@ -52310,10 +52587,10 @@ msgstr "" #: data/json/items/armor/arms_armor.json msgid "pair of 2-by-arm guards" msgid_plural "pairs of 2-by-arm guards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара дерев'яних наручів" +msgstr[1] "пари дерев'яних наручів" +msgstr[2] "пар дерев'яних наручів" +msgstr[3] "пара дерев'яних наручів" #. ~ Description for {'str': 'pair of 2-by-arm guards', 'str_pl': 'pairs of #. 2-by-arm guards'} @@ -52359,10 +52636,10 @@ msgstr "" #: data/json/items/armor/arms_armor.json msgid "pair of hard arm guards" msgid_plural "pairs of hard arm guards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара жорстких наручів" +msgstr[1] "пари жорстких наручів" +msgstr[2] "пар жорстких наручів" +msgstr[3] "пара жорстких наручів" #. ~ Description for {'str': 'pair of hard arm guards', 'str_pl': 'pairs of #. hard arm guards'} @@ -52484,10 +52761,10 @@ msgstr "" #: data/json/items/armor/arms_armor.json msgid "pair of elbow pads" msgid_plural "pairs of elbow pads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара налокітників" +msgstr[1] "пари налокітників" +msgstr[2] "пар налокітників" +msgstr[3] "пара налокітників" #. ~ Description for {'str': 'pair of elbow pads', 'str_pl': 'pairs of elbow #. pads'} @@ -52498,10 +52775,10 @@ msgstr "" #: data/json/items/armor/arms_armor.json msgid "pair of leather vambraces" msgid_plural "pairs of leather vambraces" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара шкіряних поручів" +msgstr[1] "пари шкіряних поручів" +msgstr[2] "пар шкіряних поручів" +msgstr[3] "пара шкіряних поручів" #. ~ Description for {'str': 'pair of leather vambraces', 'str_pl': 'pairs of #. leather vambraces'} @@ -52606,10 +52883,10 @@ msgstr "" #: data/mods/Generic_Guns/bandoliers/bandolier.json msgid "paper cartridge pouch" msgid_plural "paper cartridge pouches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "підсумок для паперових набоїв" +msgstr[1] "підсумки для паперових набоїв" +msgstr[2] "підсумків для паперових набоїв" +msgstr[3] "підсумок для паперових набоїв" #. ~ Description for {'str': 'paper cartridge pouch', 'str_pl': 'paper #. cartridge pouches'} @@ -52689,10 +52966,10 @@ msgstr "" #: data/json/items/armor/belts.json msgid "firefighter belt" msgid_plural "firefighter belts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пояс пожежника" +msgstr[1] "пояси пожежника" +msgstr[2] "поясів пожежника" +msgstr[3] "пояс пожежника" #. ~ Use action holster_msg for {'str': 'firefighter belt'}. #. ~ Use action holster_msg for {'str': 'survivor utility belt (holster)', @@ -52828,10 +53105,10 @@ msgstr "" #: data/json/items/armor/belts.json msgid "leather belt" msgid_plural "leather belts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряний ремінь" +msgstr[1] "шкіряних реміня" +msgstr[2] "шкіряних ременів" +msgstr[3] "шкіряний ремінь" #. ~ Use action holster_msg for {'str': 'leather belt'}. #. ~ Use action holster_msg for {'str': 'webbing belt'}. @@ -52917,10 +53194,10 @@ msgstr "" #: data/json/items/armor/belts.json msgid "tool belt" msgid_plural "tool belts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пояс для інструментів" +msgstr[1] "пояси для інструментів" +msgstr[2] "поясів для інструментів" +msgstr[3] "пояс для інструментів" #. ~ Use action holster_msg for {'str': 'tool belt'}. #: data/json/items/armor/belts.json @@ -52971,10 +53248,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of boots" msgid_plural "pairs of boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара черевиків" +msgstr[1] "пара черевиків" +msgstr[2] "пара черевиків" +msgstr[3] "пари черевиків" #. ~ Description for {'str': 'pair of boots', 'str_pl': 'pairs of boots'} #: data/json/items/armor/boots.json @@ -53000,10 +53277,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of turnout boots" msgid_plural "pairs of turnout boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара чобіт пожежника" +msgstr[1] "пари чобіт пожежника" +msgstr[2] "пар чобіт пожежника" +msgstr[3] "пара чобіт пожежника" #. ~ Description for {'str': 'pair of turnout boots', 'str_pl': 'pairs of #. turnout boots'} @@ -53016,10 +53293,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of chitinous boots" msgid_plural "pairs of chitinous boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара хітинових черевиків" +msgstr[1] "пари хітинових черевиків" +msgstr[2] "пар хітинових черевиків" +msgstr[3] "пара хітинових черевиків" #. ~ Description for {'str': 'pair of chitinous boots', 'str_pl': 'pairs of #. chitinous boots'} @@ -53108,10 +53385,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of hiking boots" msgid_plural "pairs of hiking boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара похідних черевиків" +msgstr[1] "пара похідних черевиків" +msgstr[2] "пара похідних черевиків" +msgstr[3] "пари похідних черевиків" #. ~ Description for {'str': 'pair of hiking boots', 'str_pl': 'pairs of #. hiking boots'} @@ -53200,10 +53477,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of rubber boots" msgid_plural "pairs of rubber boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара гумових чобіт" +msgstr[1] "пари гумових чобіт" +msgstr[2] "пар гумових чобіт" +msgstr[3] "пара гумових чобіт" #. ~ Description for {'str': 'pair of rubber boots', 'str_pl': 'pairs of #. rubber boots'} @@ -53229,10 +53506,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of steeltoed boots" msgid_plural "pairs of steeltoed boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара черевиків із сталевими носками" +msgstr[1] "пари черевиків із сталевими носками" +msgstr[2] "пар черевиків із сталевими носками" +msgstr[3] "пара черевиків із сталевими носками" #. ~ Description for {'str': 'pair of steeltoed boots', 'str_pl': 'pairs of #. steeltoed boots'} @@ -53259,10 +53536,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of western boots" msgid_plural "pairs of western boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара ковбойських чобіт" +msgstr[1] "пари ковбойських чобіт" +msgstr[2] "пар ковбойських чобіт" +msgstr[3] "пара ковбойських чобіт" #. ~ Description for {'str': 'pair of western boots', 'str_pl': 'pairs of #. western boots'} @@ -53410,10 +53687,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of flip-flops" msgid_plural "pairs of flip-flops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара в'єтнамок" +msgstr[1] "пари в'єтнамок" +msgstr[2] "пар в'єтнамок" +msgstr[3] "пара в'єтнамок" #. ~ Description for {'str': 'pair of flip-flops', 'str_pl': 'pairs of flip- #. flops'} @@ -53438,10 +53715,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of foot rags" msgid_plural "pairs of foot rags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара онуч" +msgstr[1] "пара онуч" +msgstr[2] "пари онуч" +msgstr[3] "пара онуч" #. ~ Description for {'str': 'pair of foot rags', 'str_pl': 'pairs of foot #. rags'} @@ -53528,10 +53805,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of knee-high boots" msgid_plural "pairs of knee-high boots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара чобіт" +msgstr[1] "пари чобіт" +msgstr[2] "пар чобіт" +msgstr[3] "пара чобіт" #. ~ Description for {'str': 'pair of knee-high boots', 'str_pl': 'pairs of #. knee-high boots'} @@ -53574,10 +53851,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of moccasins" msgid_plural "pairs of moccasins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара мокасин" +msgstr[1] "пари мокасин" +msgstr[2] "пар мокасин" +msgstr[3] "пара мокасин" #. ~ Description for {'str': 'pair of moccasins', 'str_pl': 'pairs of #. moccasins'} @@ -53602,10 +53879,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of rollerblades" msgid_plural "pairs of rollerblades" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара роликових ковзанів" +msgstr[1] "пара роликових ковзанів" +msgstr[2] "пари роликових ковзанів" +msgstr[3] "пара роликових ковзанів" #. ~ Description for {'str': 'pair of rollerblades', 'str_pl': 'pairs of #. rollerblades'} @@ -53742,10 +54019,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of swimming booties" msgid_plural "pairs of swimming booties" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара черевиків для плавання" +msgstr[1] "пари черевиків для плавання" +msgstr[2] "пар черевиків для плавання" +msgstr[3] "пара черевиків для плавання" #. ~ Description for {'str': 'pair of swimming booties', 'str_pl': 'pairs of #. swimming booties'} @@ -53826,10 +54103,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of flame-resistant socks" msgid_plural "pairs of flame-resistant socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара вогнетривких шкарпеток" +msgstr[1] "пари вогнетривких шкарпеток" +msgstr[2] "пар вогнетривких шкарпеток" +msgstr[3] "пара вогнетривких шкарпеток" #. ~ Description for {'str': 'pair of flame-resistant socks', 'str_pl': 'pairs #. of flame-resistant socks'} @@ -53843,10 +54120,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of socks" msgid_plural "pairs of socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара шкарпеток" +msgstr[1] "пари шкарпеток" +msgstr[2] "пар шкарпеток" +msgstr[3] "пара шкарпеток" #. ~ Description for {'str': 'pair of socks', 'str_pl': 'pairs of socks'} #: data/json/items/armor/boots.json @@ -53872,10 +54149,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of bag socks" msgid_plural "pairs of bag socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара шкарпеток з пакетиків" +msgstr[1] "пари шкарпеток з пакетиків" +msgstr[2] "пар шкарпеток з пакетиків" +msgstr[3] "пара шкарпеток з пакетиків" #. ~ Description for {'str': 'pair of bag socks', 'str_pl': 'pairs of bag #. socks'} @@ -53886,10 +54163,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of disposable bowling socks" msgid_plural "pairs of disposable bowling socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара одноразових шкарпеток для боулінгу" +msgstr[1] "пари одноразових шкарпеток для боулінгу" +msgstr[2] "пар одноразових шкарпеток для боулінгу" +msgstr[3] "пара одноразових шкарпеток для боулінгу" #. ~ Description for {'str': 'pair of disposable bowling socks', 'str_pl': #. 'pairs of disposable bowling socks'} @@ -53902,10 +54179,10 @@ msgstr "" #: data/json/items/armor/boots.json msgid "pair of wool socks" msgid_plural "pairs of wool socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара вовняних шкарпеток" +msgstr[1] "пари вовняних шкарпеток" +msgstr[2] "пар вовняних шкарпеток" +msgstr[3] "пара вовняних шкарпеток" #. ~ Description for {'str': 'pair of wool socks', 'str_pl': 'pairs of wool #. socks'} @@ -54223,10 +54500,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "rain coat" msgid_plural "rain coats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дощовик" +msgstr[1] "дощовики" +msgstr[2] "дощовиків" +msgstr[3] "дощовик" #. ~ Description for {'str': 'rain coat'} #: data/json/items/armor/coats.json @@ -54383,10 +54660,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "army jacket" msgid_plural "army jacket" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "армійська куртка" +msgstr[1] "армійські куртки" +msgstr[2] "армійських курток" +msgstr[3] "армійська куртка" #. ~ Description for {'str_sp': 'army jacket'} #: data/json/items/armor/coats.json @@ -54441,10 +54718,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "jean jacket" msgid_plural "jean jackets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "джинсова куртка" +msgstr[1] "джинсові куртки" +msgstr[2] "джинсових курток" +msgstr[3] "джинсова куртка" #. ~ Description for {'str': 'jean jacket'} #: data/json/items/armor/coats.json @@ -54460,10 +54737,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "leather jacket" msgid_plural "leather jackets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряна куртка" +msgstr[1] "шкіряні куртки" +msgstr[2] "шкіряних курток" +msgstr[3] "шкіряна куртка" #. ~ Description for {'str': 'leather jacket'} #: data/json/items/armor/coats.json @@ -54475,10 +54752,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "red leather jacket" msgid_plural "red leather jackets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "червона шкіряна куртка" +msgstr[1] "червоні шкіряні куртки" +msgstr[2] "червоних шкіряних курток" +msgstr[3] "червона шкіряна куртка" #. ~ Description for {'str': 'red leather jacket'} #: data/json/items/armor/coats.json @@ -54490,10 +54767,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "light jacket" msgid_plural "light jackets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "легка куртка" +msgstr[1] "легкі куртки" +msgstr[2] "легких курток" +msgstr[3] "легка куртка" #. ~ Description for {'str': 'light jacket'} #: data/json/items/armor/coats.json @@ -54503,10 +54780,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "windbreaker" msgid_plural "windbreakers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "вітровка" +msgstr[1] "вітровки" +msgstr[2] "вітровок" +msgstr[3] "вітровка" #. ~ Description for {'str': 'windbreaker'} #: data/json/items/armor/coats.json @@ -54981,10 +55258,10 @@ msgstr "" #: data/json/items/armor/coats.json msgid "army winter jacket" msgid_plural "army winter jackets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "армійська зимова куртка" +msgstr[1] "армійські зимові куртки" +msgstr[2] "армійських зимових курток" +msgstr[3] "армійська зимова куртка" #. ~ Description for {'str': 'army winter jacket'} #: data/json/items/armor/coats.json @@ -55029,10 +55306,10 @@ msgstr "" #: data/json/items/armor/eyewear.json msgid "pair of fit-over sunglasses" msgid_plural "pairs of fit-over sunglasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "відкидні сонячні окуляри" +msgstr[1] "відкидні сонячні окуляри" +msgstr[2] "відкидних сонячних окулярів" +msgstr[3] "відкидні сонячні окуляри" #. ~ Description for {'str': 'pair of fit-over sunglasses', 'str_pl': 'pairs #. of fit-over sunglasses'} @@ -55077,10 +55354,10 @@ msgstr "" #: data/json/items/armor/eyewear.json msgid "pair of eyeglasses" msgid_plural "pairs of eyeglasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "окуляри" +msgstr[1] "окулярів" +msgstr[2] "окулярів" +msgstr[3] "окуляри" #. ~ Description for {'str': 'pair of eyeglasses', 'str_pl': 'pairs of #. eyeglasses'} @@ -55109,10 +55386,10 @@ msgstr "" #: data/json/items/armor/eyewear.json msgid "pair of reading glasses" msgid_plural "pairs of reading glasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "окуляри для читання" +msgstr[1] "окулярів для читання" +msgstr[2] "окулярів для читання" +msgstr[3] "окуляри для читання" #. ~ Description for {'str': 'pair of reading glasses', 'str_pl': 'pairs of #. reading glasses'} @@ -55157,10 +55434,10 @@ msgstr "" #: data/json/items/armor/eyewear.json msgid "pair of welding goggles" msgid_plural "pairs of welding goggles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "окуляри для зварювання" +msgstr[1] "окулярів для зварювання" +msgstr[2] "окулярів для зварювання" +msgstr[3] "окуляри для зварювання" #. ~ Description for {'str': 'pair of welding goggles', 'str_pl': 'pairs of #. welding goggles'} @@ -55345,10 +55622,10 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "pair of leather armor gauntlets" msgid_plural "pairs of leather armor gauntlets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара шкіряних бронерукавиць" +msgstr[1] "пари шкіряних бронерукавиць" +msgstr[2] "пар шкіряних бронерукавиць" +msgstr[3] "пара шкіряних бронерукавиць" #. ~ Description for {'str': 'pair of leather armor gauntlets', 'str_pl': #. 'pairs of leather armor gauntlets'} @@ -55481,10 +55758,10 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "pair of leather gloves" msgid_plural "pairs of leather gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара шкіряних рукавиць" +msgstr[1] "пари шкіряних рукавиць" +msgstr[2] "пар шкіряних рукавиць" +msgstr[3] "пара шкіряних рукавиць" #. ~ Description for {'str': 'pair of leather gloves', 'str_pl': 'pairs of #. leather gloves'} @@ -55509,10 +55786,10 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "pair of glove liners" msgid_plural "pairs of glove liners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара рукавичок-підкладок" +msgstr[1] "пари рукавичок-підкладок" +msgstr[2] "пар рукавичок-підкладок" +msgstr[3] "пара рукавичок-підкладок" #. ~ Description for {'str': 'pair of glove liners', 'str_pl': 'pairs of glove #. liners'} @@ -55649,10 +55926,10 @@ msgstr "" #: data/json/items/armor/gloves.json msgid "pair of wool gloves" msgid_plural "pairs of wool gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара вовняних рукавичок" +msgstr[1] "пари вовняних рукавичок" +msgstr[2] "пар вовняних рукавичок" +msgstr[3] "пара вовняних рукавичок" #. ~ Description for {'str': 'pair of wool gloves', 'str_pl': 'pairs of wool #. gloves'} @@ -55895,10 +56172,10 @@ msgstr "" #: data/json/items/armor/hats.json msgid "ten-gallon hat" msgid_plural "ten-gallon hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "десятигалонний капелюх" +msgstr[1] "десятигалонних капелюхи" +msgstr[2] "десятигалонних капелюхів" +msgstr[3] "десятигалонний капелюх" #. ~ Description for {'str': 'ten-gallon hat'} #: data/json/items/armor/hats.json @@ -55951,10 +56228,10 @@ msgstr "" #: data/json/items/armor/hats.json msgid "cowboy hat" msgid_plural "cowboy hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ковбойський капелюх" +msgstr[1] "ковбойських капелюха" +msgstr[2] "ковбойських капелюхів" +msgstr[3] "ковбойський капелюх" #. ~ Description for {'str': 'cowboy hat'} #: data/json/items/armor/hats.json @@ -56042,10 +56319,10 @@ msgstr "" #: data/json/items/armor/hats.json msgid "cotton hat" msgid_plural "cotton hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бавовняна шапка" +msgstr[1] "бавовняні шапки" +msgstr[2] "бавовняних шапок" +msgstr[3] "бавовняна шапка" #. ~ Description for {'str': 'cotton hat'} #: data/json/items/armor/hats.json @@ -56055,10 +56332,10 @@ msgstr "" #: data/json/items/armor/hats.json msgid "fur hat" msgid_plural "fur hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шапка із хутра" +msgstr[1] "шапки із хутра" +msgstr[2] "шапок із хутра" +msgstr[3] "шапка із хутра" #. ~ Description for {'str': 'fur hat'} #: data/json/items/armor/hats.json @@ -56114,10 +56391,10 @@ msgstr "" #: data/json/items/armor/hats.json msgid "hunting cap" msgid_plural "hunting caps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мисливська кепі" +msgstr[1] "мисливські кепі" +msgstr[2] "мисливські кепі" +msgstr[3] "мисливські кепі" #. ~ Description for {'str': 'hunting cap'} #: data/json/items/armor/hats.json @@ -56127,10 +56404,10 @@ msgstr "Червона пледова мисливська кепі з наву #: data/json/items/armor/hats.json msgid "knit hat" msgid_plural "knit hats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "в'язана шапка" +msgstr[1] "в'язані шапки" +msgstr[2] "в'язані шапки" +msgstr[3] "в'язані шапки" #. ~ Description for {'str': 'knit hat'} #: data/json/items/armor/hats.json @@ -56157,10 +56434,10 @@ msgstr "" #: data/json/items/armor/hats.json msgid "noise canceling headgear" msgid_plural "noise canceling headgears" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шумоізолюючі навушники" +msgstr[1] "шумоізолюючі навушники" +msgstr[2] "шумоізолюючих навушників" +msgstr[3] "шумоізолюючі навушники" #. ~ Description for {'str': 'noise canceling headgear'} #: data/json/items/armor/hats.json @@ -56469,10 +56746,10 @@ msgstr "" #: data/json/items/armor/helmets.json msgid "bike helmet" msgid_plural "bike helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "велосипедний шолом" +msgstr[1] "велосипедний шолом" +msgstr[2] "велосипедний шолом" +msgstr[3] "велосипедні шоломи" #. ~ Description for {'str': 'bike helmet'} #: data/json/items/armor/helmets.json @@ -56482,10 +56759,10 @@ msgstr "Шолом з пінополістиролу із товстими ст #: data/json/items/armor/helmets.json msgid "chitinous helmet" msgid_plural "chitinous helmets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "хітиновий шолом" +msgstr[1] "хітинові шоломи" +msgstr[2] "хітинових шоломів" +msgstr[3] "хітиновий шолом" #. ~ Description for {'str': 'chitinous helmet'} #: data/json/items/armor/helmets.json @@ -56556,10 +56833,10 @@ msgstr "" #: data/json/items/armor/helmets.json msgid "kabuto" msgid_plural "kabutos" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кабуто" +msgstr[1] "кабуто" +msgstr[2] "кабуто" +msgstr[3] "кабуто" #. ~ Description for {'str': 'kabuto'} #: data/json/items/armor/helmets.json @@ -56601,10 +56878,10 @@ msgstr "" #: data/json/items/armor/helmets.json msgid "helmet liner" msgid_plural "helmet liners" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "підшоломник" +msgstr[1] "підшоломника" +msgstr[2] "підшоломників" +msgstr[3] "підшоломник" #. ~ Description for {'str': 'helmet liner'} #: data/json/items/armor/helmets.json @@ -56874,10 +57151,10 @@ msgstr "" #: data/json/items/armor/holster.json msgid "bow sling" msgid_plural "bow slings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "переноска для лука" +msgstr[1] "переноски для лука" +msgstr[2] "переносок для лука" +msgstr[3] "переноска для лука" #. ~ Description for {'str': 'bow sling'} #: data/json/items/armor/holster.json @@ -56889,10 +57166,10 @@ msgstr "" #: data/json/items/armor/holster.json msgid "holster" msgid_plural "holsters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кобура" +msgstr[1] "кобури" +msgstr[2] "кобур" +msgstr[3] "кобура" #. ~ Description for {'str': 'holster'} #: data/json/items/armor/holster.json @@ -57023,10 +57300,10 @@ msgstr "" #: data/json/items/armor/hoods.json msgid "rain hood" msgid_plural "rain hoods" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "капюшон від дощу" +msgstr[1] "капюшони від дощу" +msgstr[2] "капюшонів від дощу" +msgstr[3] "капюшон від дощу" #. ~ Description for {'str': 'rain hood'} #: data/json/items/armor/hoods.json @@ -57377,10 +57654,10 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "diver's watch" msgid_plural "diver's watches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "годинник пірнальника" +msgstr[1] "годинника пірнальника" +msgstr[2] "годинників пірнальника" +msgstr[3] "годинник пірнальника" #. ~ Description for {'str': "diver's watch", 'str_pl': "diver's watches"} #: data/json/items/armor/jewelry.json @@ -57408,10 +57685,10 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "copper bracelet" msgid_plural "copper bracelets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мідний браслет" +msgstr[1] "мідні браслети" +msgstr[2] "мідних браслетів" +msgstr[3] "мідний браслет" #. ~ Description for {'str': 'copper bracelet'} #: data/json/items/armor/jewelry.json @@ -57423,10 +57700,10 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "pair of copper earrings" msgid_plural "pairs of copper earrings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара мідних сережок" +msgstr[1] "пари мідних сережок" +msgstr[2] "пар мідних сережок" +msgstr[3] "пара мідних сережок" #. ~ Description for {'str': 'pair of copper earrings', 'str_pl': 'pairs of #. copper earrings'} @@ -58548,10 +58825,10 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "wrist watch" msgid_plural "wrist watches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "наручний годинник" +msgstr[1] "наручних годинника" +msgstr[2] "наручних годинників" +msgstr[3] "наручний годинник" #. ~ Description for {'str': 'wrist watch', 'str_pl': 'wrist watches'} #: data/json/items/armor/jewelry.json @@ -58563,10 +58840,10 @@ msgstr "" #: data/json/items/armor/jewelry.json msgid "radiation badge" msgid_plural "radiation badges" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "плівковий дозиметр" +msgstr[1] "плівковий дозиметр" +msgstr[2] "плівкові дозиметри" +msgstr[3] "плівковий дозиметр" #. ~ Description for {'str': 'radiation badge'} #: data/json/items/armor/jewelry.json @@ -61984,10 +62261,10 @@ msgstr "" #: data/json/items/armor/legs_armor.json msgid "pair of knee pads" msgid_plural "pairs of knee pads" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара наколінників" +msgstr[1] "пара наколінників" +msgstr[2] "пар наколінників" +msgstr[3] "пара наколінників" #. ~ Description for {'str': 'pair of knee pads', 'str_pl': 'pairs of knee #. pads'} @@ -62131,10 +62408,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "basketball shorts" msgid_plural "basketball shorts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "баскетбольні шорти" +msgstr[1] "баскетбольні шорти" +msgstr[2] "баскетбольні шорти" +msgstr[3] "баскетбольні шорти" #. ~ Description for {'str_sp': 'basketball shorts'} #: data/json/items/armor/legs_clothes.json @@ -62212,10 +62489,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "jeans" msgid_plural "jeans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "джинси" +msgstr[1] "джинсів" +msgstr[2] "джинсів" +msgstr[3] "джинси" #. ~ Description for {'str_sp': 'jeans'} #: data/json/items/armor/legs_clothes.json @@ -62335,10 +62612,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "nanoskirt" msgid_plural "nanoskirts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "нано-спідниця" +msgstr[1] "нано-спідниці" +msgstr[2] "нано-спідниць" +msgstr[3] "нано-спідниця" #. ~ Description for {'str': 'nanoskirt'} #: data/json/items/armor/legs_clothes.json @@ -62348,10 +62625,10 @@ msgstr "Напевно, мікро-спідниця була недостатн #: data/json/items/armor/legs_clothes.json msgid "pants" msgid_plural "pants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "штани" +msgstr[1] "штанів" +msgstr[2] "штанів" +msgstr[3] "штани" #. ~ Description for {'str_sp': 'pants'} #: data/json/items/armor/legs_clothes.json @@ -62374,10 +62651,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "cargo pants" msgid_plural "cargo pants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "штани із великими карманами" +msgstr[1] "штани із великими карманами" +msgstr[2] "штанів із великими карманами" +msgstr[3] "штани із великими карманами" #. ~ Description for {'str_sp': 'cargo pants'} #: data/json/items/armor/legs_clothes.json @@ -62402,10 +62679,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "fur pants" msgid_plural "fur pants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "хутряні штани" +msgstr[1] "хутряних штанів" +msgstr[2] "хутряних штанів" +msgstr[3] "хутряні штани" #. ~ Description for {'str_sp': 'fur pants'} #: data/json/items/armor/legs_clothes.json @@ -62428,10 +62705,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "leather pants" msgid_plural "leather pants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряні штани" +msgstr[1] "шкіряних штанів" +msgstr[2] "шкіряних штанів" +msgstr[3] "шкіряні штани" #. ~ Description for {'str_sp': 'leather pants'} #: data/json/items/armor/legs_clothes.json @@ -62510,10 +62787,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "skirt" msgid_plural "skirts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "спідниця" +msgstr[1] "спідниці" +msgstr[2] "спідниць" +msgstr[3] "спідниця" #. ~ Description for {'str': 'skirt'} #: data/json/items/armor/legs_clothes.json @@ -62527,10 +62804,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "leather skirt" msgid_plural "leather skirts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряна спідниця" +msgstr[1] "шкіряні спідниці" +msgstr[2] "шкіряних спідниць" +msgstr[3] "шкіряна спідниця" #. ~ Description for {'str': 'leather skirt'} #: data/json/items/armor/legs_clothes.json @@ -62541,10 +62818,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "striped pants" msgid_plural "striped pants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "штани у смужку" +msgstr[1] "штанів у смужку" +msgstr[2] "штанів у смужку" +msgstr[3] "штани у смужку" #. ~ Description for {'str_sp': 'striped pants'} #: data/json/items/armor/legs_clothes.json @@ -62578,10 +62855,10 @@ msgstr "" #: data/json/items/armor/legs_clothes.json msgid "army winter pants" msgid_plural "army winter pants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "армійські зимові штани" +msgstr[1] "армійських зимових штанів" +msgstr[2] "армійських зимових штанів" +msgstr[3] "армійські зимові штани" #. ~ Description for {'str_sp': 'army winter pants'} #: data/json/items/armor/legs_clothes.json @@ -62606,10 +62883,10 @@ msgstr "" #: data/json/items/armor/masks.json msgid "balaclava" msgid_plural "balaclavas" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "балаклава" +msgstr[1] "балаклави" +msgstr[2] "балаклав" +msgstr[3] "балаклава" #. ~ Description for {'str': 'balaclava'} #: data/json/items/armor/masks.json @@ -63874,10 +64151,10 @@ msgstr "" #: data/json/items/armor/sheath.json msgid "ankle sheath" msgid_plural "ankle sheaths" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "піхви на кісточку" +msgstr[1] "піхви на кісточку" +msgstr[2] "піхов на кісточку" +msgstr[3] "піхви на кісточку" #. ~ Description for {'str': 'ankle sheath'} #: data/json/items/armor/sheath.json @@ -63935,10 +64212,10 @@ msgstr "" #: data/json/items/armor/sheath.json msgid "spear strap" msgid_plural "spear straps" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "перев'яз для списа" +msgstr[1] "перев'язи для списа" +msgstr[2] "перев'язів для списа" +msgstr[3] "перев'яз для списа" #. ~ Use action holster_msg for {'str': 'spear strap'}. #: data/json/items/armor/sheath.json @@ -64146,10 +64423,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "backpack" msgid_plural "backpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "рюкзак" +msgstr[1] "рюкзака" +msgstr[2] "рюкзаків" +msgstr[3] "рюкзаки" #. ~ Description for {'str': 'backpack'} #: data/json/items/armor/storage.json @@ -64172,10 +64449,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "giant novelty backpack" msgid_plural "giant novelty backpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "велетенський інноваційний рюкзак" +msgstr[1] "велетенський інноваційний рюкзак" +msgstr[2] "велетенський інноваційний рюкзак" +msgstr[3] "велетенські інноваційні рюкзаки" #. ~ Description for {'str': 'giant novelty backpack'} #: data/json/items/armor/storage.json @@ -64187,10 +64464,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "leather backpack" msgid_plural "leather backpacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряний рюкзак" +msgstr[1] "шкіряний рюкзак" +msgstr[2] "шкіряний рюкзак" +msgstr[3] "шкіряні рюкзаки" #. ~ Description for {'str': 'leather backpack'} #: data/json/items/armor/storage.json @@ -64327,10 +64604,10 @@ msgstr "Легкий рюкзак із сітки, зазвичай такими #: data/json/items/armor/storage.json msgid "duffel bag" msgid_plural "duffel bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "речовий мішок" +msgstr[1] "речовий мішок" +msgstr[2] "речових мішків" +msgstr[3] "речовий мішок" #. ~ Description for {'str': 'duffel bag'} #: data/json/items/armor/storage.json @@ -64456,10 +64733,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "leather pouch" msgid_plural "leather pouches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряна торбинка" +msgstr[1] "шкіряні торбинки" +msgstr[2] "шкіряних торбинок" +msgstr[3] "шкіряна торбинка" #. ~ Description for {'str': 'leather pouch', 'str_pl': 'leather pouches'} #: data/json/items/armor/storage.json @@ -64502,10 +64779,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "makeshift sling" msgid_plural "makeshift slings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "саморобний вузол-перев'яз" +msgstr[1] "саморобні вузли-перев'язи" +msgstr[2] "саморобних вузлів-перев'язів" +msgstr[3] "саморобний вузол-перев'яз" #. ~ Description for {'str': 'makeshift sling'} #: data/json/items/armor/storage.json @@ -64600,10 +64877,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "military rucksack" msgid_plural "military rucksacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "військовий рюкзак" +msgstr[1] "військовий рюкзак" +msgstr[2] "військовий рюкзак" +msgstr[3] "військові рюкзаки" #. ~ Description for {'str': 'military rucksack'} #: data/json/items/armor/storage.json @@ -64695,10 +64972,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "survivor duffel bag" msgid_plural "survivor duffel bags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "речовий мішок виживальника" +msgstr[1] "речових мішка виживальника" +msgstr[2] "речових мішків виживальника" +msgstr[3] "речовий мішок виживальника" #. ~ Description for {'str': 'survivor duffel bag'} #: data/json/items/armor/storage.json @@ -64725,10 +65002,10 @@ msgstr "" #: data/json/items/armor/storage.json msgid "survivor rucksack" msgid_plural "survivor rucksacks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "рюкзак виживальника" +msgstr[1] "рюкзак виживальника" +msgstr[2] "рюкзак виживальника" +msgstr[3] "рюкзаки виживальника" #. ~ Description for {'str': 'survivor rucksack'} #: data/json/items/armor/storage.json @@ -64884,10 +65161,10 @@ msgstr "" #: data/json/items/armor/suits_clothes.json msgid "subject suit" msgid_plural "subject suits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "костюм піддослідного" +msgstr[1] "костюм піддослідного" +msgstr[2] "костюмів піддослідних" +msgstr[3] "костюм піддослідного" #. ~ Description for {'str': 'subject suit'} #: data/json/items/armor/suits_clothes.json @@ -65009,10 +65286,10 @@ msgstr "" #: data/json/items/armor/suits_protection.json msgid "chitinous armor" msgid_plural "chitinous armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "хітинова броня" +msgstr[1] "хітинові броні" +msgstr[2] "хітинової броні" +msgstr[3] "хітинова броня" #. ~ Description for {'str': 'chitinous armor'} #: data/json/items/armor/suits_protection.json @@ -65124,10 +65401,10 @@ msgstr "" #: data/json/items/armor/suits_protection.json msgid "ornamental plate armor" msgid_plural "ornamental plate armors" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "парадні обладунки" +msgstr[1] "парадних обладунків" +msgstr[2] "парадних обладунків" +msgstr[3] "парадні обладунки" #. ~ Description for {'str': 'ornamental plate armor'} #: data/json/items/armor/suits_protection.json @@ -65153,10 +65430,10 @@ msgstr "" #: data/json/items/armor/suits_protection.json msgid "O-yoroi" msgid_plural "O-yorois" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "О-йорой" +msgstr[1] "О-йоройя" +msgstr[2] "О-йоройїв" +msgstr[3] "О-йорой" #. ~ Description for {'str': 'O-yoroi'} #: data/json/items/armor/suits_protection.json @@ -65489,10 +65766,10 @@ msgstr "" #: data/json/items/armor/suits_protection.json msgid "leather touring suit" msgid_plural "leather touring suits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряний мотокомбінезон " +msgstr[1] "шкіряних мотокомбінезони" +msgstr[2] "шкіряних мотокомбінезонів" +msgstr[3] "шкіряний мотокомбінезон " #. ~ Description for {'str': 'leather touring suit'} #: data/json/items/armor/suits_protection.json @@ -65569,10 +65846,10 @@ msgstr "" #: data/json/items/armor/swimming.json msgid "pair of swimming trunks" msgid_plural "pairs of swimming trunks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "плавки" +msgstr[1] "плавок" +msgstr[2] "плавок" +msgstr[3] "плавки" #. ~ Description for {'str': 'pair of swimming trunks', 'str_pl': 'pairs of #. swimming trunks'} @@ -65702,10 +65979,10 @@ msgstr "" #: data/json/items/armor/swimming.json msgid "pair of swim goggles" msgid_plural "pairs of swim goggles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "окуляри для плавання" +msgstr[1] "окулярів для плавання" +msgstr[2] "окулярів для плавання" +msgstr[3] "окуляри для плавання" #. ~ Description for {'str': 'pair of swim goggles', 'str_pl': 'pairs of swim #. goggles'} @@ -65716,10 +65993,10 @@ msgstr "" #: data/json/items/armor/swimming.json msgid "pair of swimming gloves" msgid_plural "pairs of swimming gloves" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пара рукавичок для плавання" +msgstr[1] "пари рукавичок для плавання" +msgstr[2] "пар рукавичок для плавання" +msgstr[3] "пара рукавичок для плавання" #. ~ Description for {'str': 'pair of swimming gloves', 'str_pl': 'pairs of #. swimming gloves'} @@ -65942,10 +66219,10 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "Kevlar vest" msgid_plural "Kevlar vests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Кевларовий жилет" +msgstr[1] "Кевларових жилети" +msgstr[2] "Кевларових жилетів" +msgstr[3] "Кевларовий жилет" #. ~ Description for {'str': 'Kevlar vest'} #: data/json/items/armor/torso_armor.json @@ -66057,10 +66334,10 @@ msgstr "" #: data/json/items/armor/torso_clothes.json msgid "dress" msgid_plural "dresses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сукня" +msgstr[1] "сукні" +msgstr[2] "суконь" +msgstr[3] "сукня" #. ~ Description for {'str': 'dress', 'str_pl': 'dresses'} #: data/json/items/armor/torso_clothes.json @@ -66165,10 +66442,10 @@ msgstr "" #: data/json/items/armor/torso_clothes.json msgid "hoodie" msgid_plural "hoodies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "толстовка із каптуром" +msgstr[1] "толстовки із каптуром" +msgstr[2] "толстовок із каптуром" +msgstr[3] "толстовка із каптуром" #. ~ Description for {'str': 'hoodie'} #: data/json/items/armor/torso_clothes.json @@ -66434,10 +66711,10 @@ msgstr "" #: data/json/items/armor/torso_clothes.json msgid "sweater" msgid_plural "sweaters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "світер" +msgstr[1] "світер" +msgstr[2] "світер" +msgstr[3] "світери" #. ~ Description for {'str': 'sweater'} #: data/json/items/armor/torso_clothes.json @@ -66574,10 +66851,10 @@ msgstr "" #: data/json/items/armor/torso_clothes.json msgid "wool hoodie" msgid_plural "wool hoodies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "вовняна толстовка із каптуром" +msgstr[1] "вовняні толстовки із каптуром" +msgstr[2] "вовняних толстовок із каптуром" +msgstr[3] "вовняна толстовка із каптуром" #. ~ Description for {'str': 'wool hoodie'} #: data/json/items/armor/torso_clothes.json @@ -66603,10 +66880,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "camo tank top" msgid_plural "camo tank tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "камуфльована майка-безрукавка" +msgstr[1] "камуфльовані майки-безрукавки" +msgstr[2] "камуфльованих майок-безрукавок" +msgstr[3] "камуфльована майка-безрукавка" #. ~ Description for {'str': 'camo tank top'} #: data/json/items/armor/undergarment.json @@ -66616,10 +66893,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "bikini bottom" msgid_plural "bikini bottoms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "низ бікіні" +msgstr[1] "низи бікіні" +msgstr[2] "низів бікіні" +msgstr[3] "низ бікіні" #. ~ Description for {'str': 'bikini bottom'} #: data/json/items/armor/undergarment.json @@ -66629,10 +66906,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "bikini top" msgid_plural "bikini tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "верх бікіні" +msgstr[1] "верхи бікіні" +msgstr[2] "верхів бікіні" +msgstr[3] "верх бікіні" #. ~ Description for {'str': 'bikini top'} #: data/json/items/armor/undergarment.json @@ -66642,10 +66919,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "fur bikini top" msgid_plural "fur bikini tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "хутряний верх бікіні" +msgstr[1] "хутряних верхи бікіні" +msgstr[2] "хутряних верхів бікіні" +msgstr[3] "хутряний верх бікіні" #. ~ Description for {'str': 'fur bikini top'} #: data/json/items/armor/undergarment.json @@ -66655,10 +66932,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "leather bikini top" msgid_plural "leather bikini tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкіряний верх бікіні" +msgstr[1] "шкіряних верхи бікіні" +msgstr[2] "шкіряних верхів бікіні" +msgstr[3] "шкіряний верх бікіні" #. ~ Description for {'str': 'leather bikini top'} #: data/json/items/armor/undergarment.json @@ -66668,10 +66945,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "boxer briefs" msgid_plural "boxer briefs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "боксерки-брифи" +msgstr[1] "боксерки-брифи" +msgstr[2] "боксерки-брифи" +msgstr[3] "боксерки-брифи" #. ~ Description for {'str_sp': 'boxer briefs'} #: data/json/items/armor/undergarment.json @@ -66681,10 +66958,10 @@ msgstr "Споконвічне питання: боксерки чи труси- #: data/json/items/armor/undergarment.json msgid "boxer shorts" msgid_plural "boxer shorts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шорти-боксерки" +msgstr[1] "шорти-боксерки" +msgstr[2] "шорти-боксерки" +msgstr[3] "шорти-боксерки" #. ~ Description for {'str_sp': 'boxer shorts'} #: data/json/items/armor/undergarment.json @@ -66696,10 +66973,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "boy shorts" msgid_plural "boy shorts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "труси-шортики" +msgstr[1] "труси-шортики" +msgstr[2] "труси-шортики" +msgstr[3] "труси-шортики" #. ~ Description for {'str_sp': 'boy shorts'} #: data/json/items/armor/undergarment.json @@ -66712,10 +66989,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "bra" msgid_plural "bras" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бюстгальтер" +msgstr[1] "бюстгальтера" +msgstr[2] "бюстгальтерів" +msgstr[3] "бюстгальтер" #. ~ Description for {'str': 'bra'} #: data/json/items/armor/undergarment.json @@ -66726,10 +67003,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "briefs" msgid_plural "briefs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "труси-брифи" +msgstr[1] "труси-брифи" +msgstr[2] "труси-брифи" +msgstr[3] "труси-брифи" #. ~ Description for {'str_sp': 'briefs'} #: data/json/items/armor/undergarment.json @@ -66873,10 +67150,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "long underwear bottom" msgid_plural "long underwear bottoms" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "термобілизна для ніг" +msgstr[1] "термобілизни для ніг" +msgstr[2] "термобілизни для ніг" +msgstr[3] "термобілизна для ніг" #. ~ Description for {'str': 'long underwear bottom'} #: data/json/items/armor/undergarment.json @@ -66886,10 +67163,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "long underwear top" msgid_plural "long underwear tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "термобілизна для торса" +msgstr[1] "термобілизни для торса" +msgstr[2] "термобілизни для торса" +msgstr[3] "термобілизна для торса" #. ~ Description for {'str': 'long underwear top'} #: data/json/items/armor/undergarment.json @@ -66912,10 +67189,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "panties" msgid_plural "panties" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "жіночі трусики" +msgstr[1] "жіночих трусиків" +msgstr[2] "жіночих трусиків" +msgstr[3] "жіночі трусики" #. ~ Description for {'str_sp': 'panties'} #: data/json/items/armor/undergarment.json @@ -66957,10 +67234,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "tank top" msgid_plural "tank tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "майка-безрукавка" +msgstr[1] "майки-безрукавки" +msgstr[2] "майок-безрукавок" +msgstr[3] "майка-безрукавка" #. ~ Description for {'str': 'tank top'} #: data/json/items/armor/undergarment.json @@ -66985,10 +67262,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "compression top" msgid_plural "compression tops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "компресійна термофутболка" +msgstr[1] "компресійні термофутболки" +msgstr[2] "компресійних термофутболок" +msgstr[3] "компресійна термофутболка" #. ~ Description for {'str': 'compression top'} #: data/json/items/armor/undergarment.json @@ -66999,10 +67276,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "compression shorts" msgid_plural "compression shorts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "компресійні термошорти" +msgstr[1] "компресійних термошортів" +msgstr[2] "компресійних термошортів" +msgstr[3] "компресійні термошорти" #. ~ Description for {'str_sp': 'compression shorts'} #: data/json/items/armor/undergarment.json @@ -67014,10 +67291,10 @@ msgstr "" #: data/json/items/armor/undergarment.json msgid "undershirt" msgid_plural "undershirts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "майка" +msgstr[1] "майки" +msgstr[2] "майок" +msgstr[3] "майка" #. ~ Description for {'str': 'undershirt'} #: data/json/items/armor/undergarment.json @@ -67153,10 +67430,10 @@ msgstr "" #: data/json/items/book/bashing.json msgid "tactical baton defense manual" msgid_plural "tactical baton defense manuals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "«Тактика самозахисту за допомогою кийка»" +msgstr[1] "«Тактика самозахисту за допомогою кийка»" +msgstr[2] "«Тактика самозахисту за допомогою кийка»" +msgstr[3] "«Тактика самозахисту за допомогою кийка»" #. ~ Description for {'str': 'tactical baton defense manual'} #: data/json/items/book/bashing.json @@ -70069,10 +70346,10 @@ msgstr "" #: data/json/items/book/martial.json msgid "Official Taekwondo Training Manual" msgid_plural "Official Taekwondo Training Manual" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Офіційний посібник з тхеквондо " +msgstr[1] "Офіційний посібник з тхеквондо " +msgstr[2] "Офіційний посібник з тхеквондо " +msgstr[3] "Офіційний посібник з тхеквондо " #. ~ Description for {'str_sp': 'Official Taekwondo Training Manual'} #: data/json/items/book/martial.json @@ -70353,10 +70630,10 @@ msgstr "" #: data/json/items/book/misc.json msgid "comic book" msgid_plural "comic books" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "комікс" +msgstr[1] "комікси" +msgstr[2] "коміксів" +msgstr[3] "комікс" #. ~ Description for {'str': 'comic book'} #: data/json/items/book/misc.json @@ -70396,10 +70673,10 @@ msgstr "" #: data/json/items/book/misc.json msgid "children's book" msgid_plural "children's books" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дитяча книжка" +msgstr[1] "дитячих книжки" +msgstr[2] "дитячих книжок" +msgstr[3] "дитяча книжка" #. ~ Description for {'str': "children's book"} #: data/json/items/book/misc.json @@ -72202,10 +72479,10 @@ msgstr "" #: data/json/items/book/rifle.json msgid "FM 23-16 Army marksmanship manual" msgid_plural "FM 23-16 Army marksmanship manuals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "«Армійський стрілковий посібник FM 23-16»" +msgstr[1] "«Армійський стрілковий посібник FM 23-16»" +msgstr[2] "«Армійський стрілковий посібник FM 23-16»" +msgstr[3] "«Армійський стрілковий посібник FM 23-16»" #. ~ Description for {'str': 'FM 23-16 Army marksmanship manual'} #: data/json/items/book/rifle.json @@ -72357,10 +72634,10 @@ msgstr "" #: data/json/items/book/stabbing.json msgid "FM 23-25 Army bayonet manual" msgid_plural "FM 23-25 Army bayonet manuals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "«Армійський посібник з багнетного бою FM 23-25»" +msgstr[1] "«Армійський посібник з багнетного бою FM 23-25»" +msgstr[2] "«Армійський посібник з багнетного бою FM 23-25»" +msgstr[3] "«Армійський посібник з багнетного бою FM 23-25»" #. ~ Description for {'str': 'FM 23-25 Army bayonet manual'} #: data/json/items/book/stabbing.json @@ -72988,10 +73265,10 @@ msgstr[3] "" #: data/json/items/classes/gun.json msgid "rifle with manual actions" msgid_plural "rifles with manual actions" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "однозарядна гвинтівка" +msgstr[1] "однозарядна гвинтівка" +msgstr[2] "однозарядні гвинтівки" +msgstr[3] "однозарядні гвинтівки" #: data/json/items/classes/gun.json msgid "semi-automatic rifle" @@ -74609,10 +74886,10 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "chunk of meat" msgid_plural "chunks of meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шматок м'яса" +msgstr[1] "шматки м'яса" +msgstr[2] "шматків м'яса" +msgstr[3] "шматок м'яса" #. ~ Description for {'str': 'chunk of meat', 'str_pl': 'chunks of meat'} #: data/json/items/comestibles/carnivore.json @@ -75050,10 +75327,10 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "chunk of fat" msgid_plural "chunks of fat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шматок жиру" +msgstr[1] "шматки жиру" +msgstr[2] "шматків жиру" +msgstr[3] "шматок жиру" #. ~ Description for {'str': 'chunk of fat', 'str_pl': 'chunks of fat'} #: data/json/items/comestibles/carnivore.json @@ -75191,10 +75468,10 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "chunk of tainted meat" msgid_plural "chunks of tainted meat" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шматок зараженого м'яса" +msgstr[1] "шматка зараженого м'яса" +msgstr[2] "шматків зараженого м'яса" +msgstr[3] "шматок зараженого м'яса" #. ~ Description for {'str': 'chunk of tainted meat', 'str_pl': 'chunks of #. tainted meat'} @@ -75777,10 +76054,10 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "bee balm tea" msgid_plural "bee balm tea" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "чай із монарди" +msgstr[1] "чай із монарди" +msgstr[2] "чай із монарди" +msgstr[3] "чай із монарди" #. ~ Description for {'str_sp': 'bee balm tea'} #: data/json/items/comestibles/drink.json @@ -76332,10 +76609,10 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "sweet water" msgid_plural "sweet water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "солодка вода" +msgstr[1] "солодкої води" +msgstr[2] "солодкої води" +msgstr[3] "солодка вода" #. ~ Description for {'str_sp': 'sweet water'} #: data/json/items/comestibles/drink.json @@ -76395,10 +76672,10 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "clean water" msgid_plural "clean water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "чиста вода" +msgstr[1] "чистої води" +msgstr[2] "чистої води" +msgstr[3] "чиста вода" #. ~ Description for {'str_sp': 'clean water'} #: data/json/items/comestibles/drink.json @@ -76408,10 +76685,10 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "mineral water" msgid_plural "mineral water" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мінеральна вода" +msgstr[1] "мінеральної води" +msgstr[2] "мінеральної води" +msgstr[3] "мінеральна вода" #. ~ Description for {'str_sp': 'mineral water'} #: data/json/items/comestibles/drink.json @@ -76625,10 +76902,10 @@ msgstr "" #: data/json/items/comestibles/drink_other.json msgid "vinegar" msgid_plural "vinegar" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "оцет" +msgstr[1] "оцту" +msgstr[2] "оцту" +msgstr[3] "оцет" #. ~ Description for {'str_sp': 'vinegar'} #: data/json/items/comestibles/drink_other.json @@ -76950,6 +77227,58 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -77227,10 +77556,10 @@ msgstr "" #: data/json/items/comestibles/fruit_dishes.json msgid "dehydrated fruit" msgid_plural "dehydrated fruit" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сушений фрукт" +msgstr[1] "сушених фрукти" +msgstr[2] "сушених фруктів" +msgstr[3] "сушений фрукт" #. ~ Description for {'str_sp': 'dehydrated fruit'} #: data/json/items/comestibles/fruit_dishes.json @@ -77808,10 +78137,10 @@ msgstr "" #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated corn" msgid_plural "irradiated corn" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "опромінена кукурудза" +msgstr[1] "опроміненої кукурудзи" +msgstr[2] "опроміненої кукурудзи" +msgstr[3] "опромінена кукурудза" #. ~ Description for {'str_sp': 'irradiated corn'} #: data/json/items/comestibles/irradiated_veggy.json @@ -77977,10 +78306,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "popcorn kernels" msgid_plural "popcorn kernels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кукурудза під попкорн" +msgstr[1] "кукурудзи під попкорн" +msgstr[2] "кукурудзи під попкорн" +msgstr[3] "кукурудза під попкорн" #. ~ Description for {'str_sp': 'popcorn kernels'} #: data/json/items/comestibles/junkfood.json @@ -77993,10 +78322,10 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "popcorn" msgid_plural "popcorn" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "попкорн" +msgstr[1] "попкорну" +msgstr[2] "попкорну" +msgstr[3] "попкорн" #. ~ Description for {'str_sp': 'popcorn'} #: data/json/items/comestibles/junkfood.json @@ -78008,10 +78337,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "salted popcorn" msgid_plural "salted popcorn" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "солоний попкорн" +msgstr[1] "солоного попкорну" +msgstr[2] "солоного попкорну" +msgstr[3] "солоний попкорн" #. ~ Description for {'str_sp': 'salted popcorn'} #: data/json/items/comestibles/junkfood.json @@ -78021,10 +78350,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "buttered popcorn" msgid_plural "buttered popcorn" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "попкорн з маслом" +msgstr[1] "попкорну з маслом" +msgstr[2] "попкорну з маслом" +msgstr[3] "попкорн з маслом" #. ~ Description for {'str_sp': 'buttered popcorn'} #: data/json/items/comestibles/junkfood.json @@ -78103,10 +78432,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "peanut butter candy" msgid_plural "peanut butter candies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "цукерка із арахісовим маслом" +msgstr[1] "цукерки із арахісовим маслом" +msgstr[2] "цукерок із арахісовим маслом" +msgstr[3] "цукерка із арахісовим маслом" #. ~ Description for {'str': 'peanut butter candy', 'str_pl': 'peanut butter #. candies'} @@ -78117,10 +78446,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "chocolate candy" msgid_plural "chocolate candies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шоколадна цукерка" +msgstr[1] "шоколадні цукерки" +msgstr[2] "шоколадних цукерок" +msgstr[3] "шоколадна цукерка" #. ~ Description for {'str': 'chocolate candy', 'str_pl': 'chocolate candies'} #: data/json/items/comestibles/junkfood.json @@ -78144,10 +78473,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "powder candy sticks" msgid_plural "powder candy sticks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "трубочка із цукерковим порошком" +msgstr[1] "трубочки із цукерковим порошком" +msgstr[2] "трубочок із цукерковим порошком" +msgstr[3] "трубочка із цукерковим порошком" #. ~ Description for {'str_sp': 'powder candy sticks'} #: data/json/items/comestibles/junkfood.json @@ -78158,10 +78487,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "maple syrup candy" msgid_plural "maple syrup candies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "цукерка з кленового сиропу" +msgstr[1] "цукерки з кленового сиропу" +msgstr[2] "цукерок з кленового сиропу" +msgstr[3] "цукерка з кленового сиропу" #. ~ Description for {'str': 'maple syrup candy', 'str_pl': 'maple syrup #. candies'} @@ -78190,6 +78519,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -78576,10 +78906,10 @@ msgstr "" #: data/json/items/comestibles/junkfood.json msgid "uncooked corn dogs" msgid_plural "uncooked corn dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "неприготований корн-дог" +msgstr[1] "неприготованих корн-доги" +msgstr[2] "неприготованих корн-догів" +msgstr[3] "неприготований корн-дог" #. ~ Description for {'str_sp': 'uncooked corn dogs'} #: data/json/items/comestibles/junkfood.json @@ -78999,10 +79329,10 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "cracklins" msgid_plural "cracklins" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шкварки" +msgstr[1] "шкварки" +msgstr[2] "шкварки" +msgstr[3] "шкварки" #. ~ Description for {'str_sp': 'cracklins'} #: data/json/items/comestibles/meat_dishes.json @@ -79111,10 +79441,10 @@ msgstr "" #: data/json/items/comestibles/meat_dishes.json msgid "dehydrated fish" msgid_plural "dehydrated fish" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сушена риба" +msgstr[1] "сушені риби" +msgstr[2] "сушених риб" +msgstr[3] "сушена риба" #. ~ Description for {'str_sp': 'dehydrated fish'} #: data/json/items/comestibles/meat_dishes.json @@ -80261,10 +80591,10 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "Adderall" msgid_plural "Adderall" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Аддералл" +msgstr[1] "Аддераллу" +msgstr[2] "Аддераллу" +msgstr[3] "Аддералл" #. ~ Use action activation_message for {'str_sp': 'Adderall'}. #: data/json/items/comestibles/med.json @@ -80602,10 +80932,10 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "cotton balls" msgid_plural "cotton balls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ватні кульки" +msgstr[1] "ватні кульки" +msgstr[2] "ватні кульки" +msgstr[3] "ватні кульки" #. ~ Description for {'str_sp': 'cotton balls'} #: data/json/items/comestibles/med.json @@ -80637,10 +80967,10 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "non-drowsy cough syrup" msgid_plural "non-drowsy cough syrup" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сироп від кашлю (без присипляння)" +msgstr[1] "сиропу від кашлю (без присипляння)" +msgstr[2] "сиропу від кашлю (без присипляння)" +msgstr[3] "сироп від кашлю (без присипляння)" #. ~ Description for {'str_sp': 'non-drowsy cough syrup'} #: data/json/items/comestibles/med.json @@ -80993,12 +81323,13 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "жувальна гумка" +msgstr[1] "жувальна гумка" +msgstr[2] "жувальна гумка" +msgstr[3] "жувальні гумки" #. ~ Description for {'str_sp': 'chewing gum'} #: data/json/items/comestibles/med.json @@ -81177,10 +81508,10 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "cough syrup" msgid_plural "cough syrup" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сироп від кашлю" +msgstr[1] "сиропу від кашлю" +msgstr[2] "сиропу від кашлю" +msgstr[3] "сироп від кашлю" #. ~ Description for {'str_sp': 'cough syrup'} #: data/json/items/comestibles/med.json @@ -81263,10 +81594,10 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "poppy cough syrup" msgid_plural "poppy cough syrup" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "маковий сироп від кашлю" +msgstr[1] "макового сиропу від кашлю" +msgstr[2] "макового сиропу від кашлю" +msgstr[3] "маковий сироп від кашлю" #. ~ Description for {'str_sp': 'poppy cough syrup'} #: data/json/items/comestibles/med.json @@ -81679,10 +82010,10 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "cattail jelly" msgid_plural "cattail jellies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "желе із рогозу" +msgstr[1] "желе із рогозу" +msgstr[2] "желе із рогозу" +msgstr[3] "желе із рогозу" #. ~ Description for {'str': 'cattail jelly', 'str_pl': 'cattail jellies'} #: data/json/items/comestibles/med.json @@ -81713,10 +82044,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE" msgid_plural "MREs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок" +msgstr[1] "сухпайка" +msgstr[2] "сухпайків" +msgstr[3] "сухпайки" #. ~ Description for {'str': 'MRE'} #: data/json/items/comestibles/mre.json @@ -81726,10 +82057,10 @@ msgstr "" #: data/json/items/comestibles/mre.json data/json/obsoletion/items.json msgid "MRE small box" msgid_plural "MRE small boxes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "маленька коробка сухпайка" +msgstr[1] "маленькі коробки сухпайка" +msgstr[2] "маленьких коробкок сухпайка" +msgstr[3] "маленькі коробки сухпайків" #. ~ Description for {'str': 'MRE small box', 'str_pl': 'MRE small boxes'} #: data/json/items/comestibles/mre.json data/json/obsoletion/items.json @@ -81752,10 +82083,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Accessory Pack" msgid_plural "MREs - Accessory Packs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "набір аксесуарів сухпайка" +msgstr[1] "набори аксесуарів сухпайка" +msgstr[2] "наборів аксесуарів сухпайка" +msgstr[3] "набори аксесуарів сухпайка" #. ~ Description for {'str': 'MRE - Accessory Pack', 'str_pl': 'MREs - #. Accessory Packs'} @@ -81768,10 +82099,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Dessert Pack" msgid_plural "MREs - Dessert Packs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "десертний набір сухпайка" +msgstr[1] "десертні набори сухпайка" +msgstr[2] "десертних наборів сухпайка" +msgstr[3] "десертні набори сухпайка" #. ~ Description for {'str': 'MRE - Dessert Pack', 'str_pl': 'MREs - Dessert #. Packs'} @@ -81784,10 +82115,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chili & Beans" msgid_plural "MREs - Chili & Beans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Чилі з квасолею\"" +msgstr[1] "сухпайка \"Чилі з квасолею\"" +msgstr[2] "сухпайків \"Чилі з квасолею\"" +msgstr[3] "сухпайки \"Чилі з квасолею\"" #. ~ Description for {'str': 'MRE - Chili & Beans', 'str_pl': 'MREs - Chili & #. Beans'} @@ -81801,10 +82132,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - BBQ Beef" msgid_plural "MREs - BBQ Beef" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Барбекю з яловичини\"" +msgstr[1] "сухпайка \"Барбекю з яловичини\"" +msgstr[2] "сухпайків \"Барбекю з яловичини\"" +msgstr[3] "сухпайки \"Барбекю з яловичини\"" #. ~ Description for {'str': 'MRE - BBQ Beef', 'str_pl': 'MREs - BBQ Beef'} #: data/json/items/comestibles/mre.json @@ -81817,10 +82148,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chicken & Noodles" msgid_plural "MREs - Chicken & Noodles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Курка з локшиною\"" +msgstr[1] "сухпайка \"Курка з локшиною\"" +msgstr[2] "сухпайків \"Курка з локшиною\"" +msgstr[3] "сухпайки \"Курка з локшиною\"" #. ~ Description for {'str': 'MRE - Chicken & Noodles', 'str_pl': 'MREs - #. Chicken & Noodles'} @@ -81834,10 +82165,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Spaghetti" msgid_plural "MREs - Spaghetti" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Спагеті\"" +msgstr[1] "сухпайка \"Спагеті\"" +msgstr[2] "сухпайків \"Спагеті\"" +msgstr[3] "сухпайки \"Спагеті\"" #. ~ Description for {'str': 'MRE - Spaghetti', 'str_pl': 'MREs - Spaghetti'} #: data/json/items/comestibles/mre.json @@ -81850,10 +82181,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chicken Chunks" msgid_plural "MREs - Chicken Chunks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Курятина\"" +msgstr[1] "сухпайка \"Курятина\"" +msgstr[2] "сухпайків \"Курятина\"" +msgstr[3] "сухпайки \"Курятина\"" #. ~ Description for {'str': 'MRE - Chicken Chunks', 'str_pl': 'MREs - Chicken #. Chunks'} @@ -81867,10 +82198,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Beef Taco" msgid_plural "MREs - Beef Taco" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Яловиче тако\"" +msgstr[1] "сухпайка \"Яловиче тако\"" +msgstr[2] "сухпайків \"Яловиче тако\"" +msgstr[3] "сухпайки \"Яловиче тако\"" #. ~ Description for {'str': 'MRE - Beef Taco', 'str_pl': 'MREs - Beef Taco'} #: data/json/items/comestibles/mre.json @@ -81883,10 +82214,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Beef Brisket" msgid_plural "MREs - Beef Brisket" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Яловича грудина\"" +msgstr[1] "сухпайка \"Яловича грудина\"" +msgstr[2] "сухпайків \"Яловича грудина\"" +msgstr[3] "сухпайки \"Яловича грудина\"" #. ~ Description for {'str': 'MRE - Beef Brisket', 'str_pl': 'MREs - Beef #. Brisket'} @@ -81900,10 +82231,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Meatballs & Marinara" msgid_plural "MREs - Meatballs & Marinara" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Фрикадельки у соусі\"" +msgstr[1] "сухпайка \"Фрикадельки у соусі\"" +msgstr[2] "сухпайків \"Фрикадельки у соусі\"" +msgstr[3] "сухпайки \"Фрикадельки у соусі\"" #. ~ Description for {'str': 'MRE - Meatballs & Marinara', 'str_pl': 'MREs - #. Meatballs & Marinara'} @@ -81917,10 +82248,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Beef Stew" msgid_plural "MREs - Beef Stew" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Рагу з яловичини\"" +msgstr[1] "сухпайка \"Рагу з яловичини\"" +msgstr[2] "сухпайків \"Рагу з яловичини\"" +msgstr[3] "сухпайки \"Рагу з яловичини\"" #. ~ Description for {'str': 'MRE - Beef Stew', 'str_pl': 'MREs - Beef Stew'} #: data/json/items/comestibles/mre.json @@ -81933,10 +82264,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Chili & Macaroni" msgid_plural "MREs - Chili & Macaroni" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Макарони з чилі\"" +msgstr[1] "сухпайка \"Макарони з чилі\"" +msgstr[2] "сухпайків \"Макарони з чилі\"" +msgstr[3] "сухпайки \"Макарони з чилі\"" #. ~ Description for {'str': 'MRE - Chili & Macaroni', 'str_pl': 'MREs - Chili #. & Macaroni'} @@ -81950,10 +82281,10 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "MRE - Vegetarian Taco" msgid_plural "MREs - Vegetarian Taco" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сухпайок \"Вегетаріанське тако\"" +msgstr[1] "сухпайка \"Вегетаріанське тако\"" +msgstr[2] "сухпайків \"Вегетаріанське тако\"" +msgstr[3] "сухпайки \"Вегетаріанське тако\"" #. ~ Description for {'str': 'MRE - Vegetarian Taco', 'str_pl': 'MREs - #. Vegetarian Taco'} @@ -83386,10 +83717,10 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "almonds" msgid_plural "almonds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мигдаль" +msgstr[1] "мигдаль" +msgstr[2] "мигдаль" +msgstr[3] "мигдаль" #. ~ Description for {'str_sp': 'almonds'} #: data/json/items/comestibles/nuts.json @@ -83399,10 +83730,10 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "almond pulp" msgid_plural "almond pulp" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мигдалевий жмих" +msgstr[1] "мигдалевий жмих" +msgstr[2] "мигдалевий жмих" +msgstr[3] "мигдалевий жмих" #. ~ Description for {'str_sp': 'almond pulp'} #: data/json/items/comestibles/nuts.json @@ -83413,10 +83744,10 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted almonds" msgid_plural "roasted almonds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "смажений мигдаль" +msgstr[1] "смажений мигдаль" +msgstr[2] "смажений мигдаль" +msgstr[3] "смажений мигдаль" #. ~ Description for {'str_sp': 'roasted almonds'} #: data/json/items/comestibles/nuts.json @@ -83634,10 +83965,10 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "acorns" msgid_plural "acorns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "жолуді" +msgstr[1] "жолудів" +msgstr[2] "жолудів" +msgstr[3] "жолуді" #. ~ Description for {'str_sp': 'acorns'} #: data/json/items/comestibles/nuts.json @@ -83649,10 +83980,10 @@ msgstr "" #: data/json/items/comestibles/nuts.json msgid "roasted acorns" msgid_plural "roasted acorns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "смажені жолуді" +msgstr[1] "смажених жолудів" +msgstr[2] "смажених жолудів" +msgstr[3] "смажені жолуді" #. ~ Description for {'str_sp': 'roasted acorns'} #: data/json/items/comestibles/nuts.json @@ -84166,10 +84497,10 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "chitin powder" msgid_plural "chitin powder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "хітиновний порошок" +msgstr[1] "хітинового порошку" +msgstr[2] "хітинового порошку" +msgstr[3] "хітиновний порошок" #. ~ Description for {'str_sp': 'chitin powder'} #: data/json/items/comestibles/other.json @@ -84405,10 +84736,10 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "embalmed human brain" msgid_plural "embalmed human brains" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "забальзамований людський мозок" +msgstr[1] "забальзамований людський мозок" +msgstr[2] "забальзамований людський мозок" +msgstr[3] "забальзамовані людські мізки" #. ~ Description for {'str': 'embalmed human brain'} #: data/json/items/comestibles/other.json @@ -84451,10 +84782,10 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "dog food" msgid_plural "dog food" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "собачий корм" +msgstr[1] "собачий корм" +msgstr[2] "собачий корм" +msgstr[3] "собачий корм" #. ~ Description for {'str_sp': 'dog food'} #: data/json/items/comestibles/other.json @@ -84464,10 +84795,10 @@ msgstr "" #: data/json/items/comestibles/other.json msgid "cat food" msgid_plural "cat food" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "котячий корм" +msgstr[1] "котячий корм" +msgstr[2] "котячий корм" +msgstr[3] "котячий корм" #. ~ Description for {'str_sp': 'cat food'} #: data/json/items/comestibles/other.json @@ -84541,10 +84872,10 @@ msgstr "" #: data/json/items/comestibles/protein.json msgid "protein powder" msgid_plural "protein powder" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "протеїновний порошок" +msgstr[1] "протеїновний порошок" +msgstr[2] "протеїновний порошок" +msgstr[3] "протеїновний порошок" #. ~ Conditional name for {'str_sp': 'protein powder'} when FLAG matches #. CANNIBALISM @@ -85219,10 +85550,10 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "corn" msgid_plural "corn" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кукурудза" +msgstr[1] "кукурудзи" +msgstr[2] "кукурудзи" +msgstr[3] "кукурудза" #. ~ Description for {'str_sp': 'corn'} #: data/json/items/comestibles/raw_veggy.json @@ -85359,10 +85690,10 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "hops flower" msgid_plural "hops flowers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "квітка хмелю" +msgstr[1] "квітка хмелю" +msgstr[2] "квітки хмелю" +msgstr[3] "квітки хмелю" #. ~ Description for {'str': 'hops flower'} #: data/json/items/comestibles/raw_veggy.json @@ -85622,10 +85953,10 @@ msgstr "" #: data/json/items/comestibles/raw_veggy.json msgid "wild vegetables" msgid_plural "wild vegetables" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дикі овочі" +msgstr[1] "диких овочей" +msgstr[2] "дикі овочі" +msgstr[3] "дикі овочі" #. ~ Description for {'str_sp': 'wild vegetables'} #: data/json/items/comestibles/raw_veggy.json @@ -85983,10 +86314,10 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "seeds" msgid_plural "seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "насіння" +msgstr[1] "насіння" +msgstr[2] "насіння" +msgstr[3] "насіння" #: data/json/items/comestibles/seed.json msgid "fruit seeds" @@ -86285,10 +86616,10 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "cotton seeds" msgid_plural "cotton seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "насіння бавовника" +msgstr[1] "насіння бавовника" +msgstr[2] "насіння бавовника" +msgstr[3] "насіння бавовника" #. ~ Description for {'str_sp': 'cotton seeds'} #: data/json/items/comestibles/seed.json @@ -86358,10 +86689,10 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "cattail seeds" msgid_plural "cattail seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "насіння рогозу" +msgstr[1] "насіння рогозу" +msgstr[2] "насіння рогозу" +msgstr[3] "насіння рогозу" #. ~ Description for {'str_sp': 'cattail seeds'} #: data/json/items/comestibles/seed.json @@ -86490,10 +86821,10 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "corn seeds" msgid_plural "corn seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "насіння кукурудзи" +msgstr[1] "насіння кукурудзи" +msgstr[2] "насіння кукурудзи" +msgstr[3] "насіння кукурудзи" #. ~ Description for {'str_sp': 'corn seeds'} #: data/json/items/comestibles/seed.json @@ -86711,10 +87042,10 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "bee balm seeds" msgid_plural "bee balm seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "насіння монарди" +msgstr[1] "насіння монарди" +msgstr[2] "насіння монарди" +msgstr[3] "насіння монарди" #. ~ Description for {'str_sp': 'bee balm seeds'} #: data/json/items/comestibles/seed.json @@ -86750,10 +87081,10 @@ msgstr "" #: data/json/items/comestibles/seed.json msgid "wild herb seeds" msgid_plural "wild herb seeds" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "насіння дикої трави" +msgstr[1] "насіння дикої трави" +msgstr[2] "насіння дикої трави" +msgstr[3] "насіння дикої трави" #. ~ Description for {'str_sp': 'wild herb seeds'} #: data/json/items/comestibles/seed.json @@ -87349,10 +87680,10 @@ msgstr "" #: data/json/items/comestibles/spice.json msgid "wild herbs" msgid_plural "wild herbs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дикі трави" +msgstr[1] "дикі трави" +msgstr[2] "дикі трави" +msgstr[3] "дикі трави" #. ~ Description for {'str_sp': 'wild herbs'} #: data/json/items/comestibles/spice.json @@ -88201,10 +88532,10 @@ msgstr "" #: data/json/items/comestibles/wheat.json msgid "flour" msgid_plural "flour" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "борошно" +msgstr[1] "борошна" +msgstr[2] "борошна" +msgstr[3] "борошно" #. ~ Description for {'str_sp': 'flour'} #: data/json/items/comestibles/wheat.json @@ -88334,6 +88665,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -88496,10 +88828,10 @@ msgstr "" #: data/json/items/corpses/corpses.json msgid "corpse" msgid_plural "corpses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "труп" +msgstr[1] "трупи" +msgstr[2] "трупів" +msgstr[3] "труп" #. ~ Conditional name for {'str': 'corpse'} when FLAG matches FIELD_DRESS #. ~ Conditional name for {'str': 'corpse'} when FLAG matches @@ -89624,10 +89956,10 @@ msgstr "" #: data/json/items/generic/bedding.json msgid "sheet" msgid_plural "sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "штора" +msgstr[1] "штори" +msgstr[2] "штор" +msgstr[3] "штора" #. ~ Description for {'str': 'sheet'} #: data/json/items/generic/bedding.json @@ -89639,10 +89971,10 @@ msgstr "" #: data/json/items/generic/bedding.json msgid "blanket" msgid_plural "blankets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ковдра" +msgstr[1] "ковдри" +msgstr[2] "ковдр" +msgstr[3] "ковдра" #. ~ Description for {'str': 'blanket'} #: data/json/items/generic/bedding.json @@ -90391,10 +90723,10 @@ msgstr[3] "" #: data/json/items/generic/dining_kitchen.json msgid "generic cook pot" msgid_plural "generic cook pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "звичайна каструля" +msgstr[1] "звичайні каструлі" +msgstr[2] "звичайних каструль" +msgstr[3] "звичайна каструля" #: data/json/items/generic/dining_kitchen.json msgid "ceramic plate" @@ -90412,10 +90744,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "ceramic bowl" msgid_plural "ceramic bowls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "керамічна миска" +msgstr[1] "керамічні миски" +msgstr[2] "керамічних мисок" +msgstr[3] "керамічна миска" #. ~ Description for {'str': 'ceramic bowl'} #: data/json/items/generic/dining_kitchen.json @@ -90548,10 +90880,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "pewter bowl" msgid_plural "pewter bowls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "олов'яна миска" +msgstr[1] "олов'яні миски" +msgstr[2] "олов'яних мисок" +msgstr[3] "олов'яна миска" #. ~ Description for {'str': 'pewter bowl'} #: data/json/items/generic/dining_kitchen.json @@ -90561,10 +90893,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "drinking glass" msgid_plural "drinking glasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "склянка" +msgstr[1] "склянки" +msgstr[2] "склянок" +msgstr[3] "склянка" #. ~ Description for {'str': 'drinking glass', 'str_pl': 'drinking glasses'} #: data/json/items/generic/dining_kitchen.json @@ -90589,10 +90921,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "glass bowl" msgid_plural "glass bowls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "скляна миска" +msgstr[1] "скляні миски" +msgstr[2] "скляних мисок" +msgstr[3] "скляна миска" #. ~ Description for {'str': 'glass bowl'} #: data/json/items/generic/dining_kitchen.json @@ -90617,10 +90949,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "plastic bowl" msgid_plural "plastic bowls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластикова мисочка" +msgstr[1] "пластикові мисочки" +msgstr[2] "пластикових мисочок" +msgstr[3] "пластикова мисочка" #. ~ Description for {'str': 'plastic bowl'} #: data/json/items/generic/dining_kitchen.json @@ -90717,10 +91049,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "pot" msgid_plural "pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "каструля" +msgstr[1] "каструлі" +msgstr[2] "каструль" +msgstr[3] "каструля" #. ~ Description for {'str': 'pot'} #: data/json/items/generic/dining_kitchen.json @@ -90730,10 +91062,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "cast-iron pot" msgid_plural "cast-iron pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "чавунна каструля" +msgstr[1] "чавунні каструлі" +msgstr[2] "чавунних каструль" +msgstr[3] "чавунна каструля" #. ~ Description for {'str': 'cast-iron pot'} #: data/json/items/generic/dining_kitchen.json @@ -90744,10 +91076,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "copper pot" msgid_plural "copper pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мідна каструля" +msgstr[1] "мідні каструлі" +msgstr[2] "мідних каструль" +msgstr[3] "мідна каструля" #. ~ Description for {'str': 'copper pot'} #: data/json/items/generic/dining_kitchen.json @@ -90789,10 +91121,10 @@ msgstr "" #: data/json/items/generic/dining_kitchen.json msgid "canning pot" msgid_plural "canning pots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "каструля для консервації" +msgstr[1] "каструлі для консервації" +msgstr[2] "каструль для консервації" +msgstr[3] "каструля для консервації" #. ~ Description for {'str': 'canning pot'} #: data/json/items/generic/dining_kitchen.json @@ -91021,10 +91353,10 @@ msgstr "" #: data/json/items/generic/spares.json msgid "spare parts" msgid_plural "spare parts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "витратний матеріал" +msgstr[1] "витратний матеріал" +msgstr[2] "витратний матеріал" +msgstr[3] "витратні матеріали" #. ~ Description for {'str_sp': 'spare parts'} #: data/json/items/generic/spares.json @@ -91244,10 +91576,10 @@ msgstr "" #: data/json/items/generic/string.json msgid "long string" msgid_plural "long strings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "довга шворка" +msgstr[1] "довга шворка" +msgstr[2] "довга шворка" +msgstr[3] "довгі шворки" #. ~ Description for {'str': 'long string'} #: data/json/items/generic/string.json @@ -91257,10 +91589,10 @@ msgstr "" #: data/json/items/generic/string.json msgid "short rope" msgid_plural "short ropes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "коротка мотузка" +msgstr[1] "короткі мотузки" +msgstr[2] "коротких мотузок" +msgstr[3] "коротка мотузка" #. ~ Description for {'str': 'short rope'} #: data/json/items/generic/string.json @@ -91271,10 +91603,10 @@ msgstr "" #: data/json/items/generic/string.json msgid "long rope" msgid_plural "long ropes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "довга мотузка" +msgstr[1] "довгі мотузки" +msgstr[2] "довгих мотузок" +msgstr[3] "довга мотузка" #. ~ Description for {'str': 'long rope'} #: data/json/items/generic/string.json @@ -94750,10 +95082,10 @@ msgstr "" #: data/json/items/gun/flintlock.json msgid "flintlock pistol" msgid_plural "flintlock pistols" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кременевий пістоль" +msgstr[1] "кременеві пістолі" +msgstr[2] "кременевих пістолів" +msgstr[3] "кременевий пістоль" #: data/json/items/gun/flintlock.json msgid "" @@ -94909,10 +95241,10 @@ msgstr "" #: data/json/items/gun/nail.json msgid "nail gun" msgid_plural "nail guns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "цвяхозабивач" +msgstr[1] "цвяхозабивача" +msgstr[2] "цвяхозабивачів" +msgstr[3] "цвяхозабивач" #: data/json/items/gun/nail.json msgid "" @@ -95499,10 +95831,10 @@ msgstr "" #: data/json/items/gun/ups.json msgid "A7 laser rifle" msgid_plural "A7 laser rifles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "лазерна гвинтівка A7" +msgstr[1] "лазерні гвинтівки A7" +msgstr[2] "лазерних гвинтівок A7" +msgstr[3] "лазерна гвинтівка A7" #: data/json/items/gun/ups.json msgid "" @@ -95515,10 +95847,10 @@ msgstr "" #: data/json/items/gun/ups.json msgid "V29 laser pistol" msgid_plural "V29 laser pistols" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "лазерний пістолет V29" +msgstr[1] "лазерні пістолета V29" +msgstr[2] "лазерних пістолетів V29" +msgstr[3] "лазерний пістолет V29" #: data/json/items/gun/ups.json msgid "" @@ -95529,10 +95861,10 @@ msgstr "" #: data/json/items/gunmod/accessories.json msgid "arrow rest" msgid_plural "arrow rests" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "полка для лука" +msgstr[1] "полки для лука" +msgstr[2] "полок для лука" +msgstr[3] "полка для лука" #: data/json/items/gunmod/accessories.json msgid "" @@ -96895,10 +97227,10 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "underbarrel laser sight" msgid_plural "underbarrel laser sights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "підствольний цілевказівник" +msgstr[1] "підствольних цілевказівники" +msgstr[2] "підствольних цілевказівників" +msgstr[3] "підствольний цілевказівник" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -100085,10 +100417,10 @@ msgstr "" #: data/json/items/melee/bludgeons.json msgid "nail bat" msgid_plural "nail bats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бита із цвяхами" +msgstr[1] "бити із цвяхами" +msgstr[2] "бит із цвяхами" +msgstr[3] "бита із цвяхами" #. ~ Description for {'str': 'nail bat'} #: data/json/items/melee/bludgeons.json @@ -100732,10 +101064,10 @@ msgstr "" #: data/json/items/melee/bludgeons.json msgid "rock in a sock" msgid_plural "rocks in socks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Камінь у шкарпетці" +msgstr[1] "Камінь у шкарпетці" +msgstr[2] "Камінь у шкарпетці" +msgstr[3] "Камні у шкарпетках" #. ~ Description for {'str': 'rock in a sock', 'str_pl': 'rocks in socks'} #: data/json/items/melee/bludgeons.json @@ -100915,10 +101247,10 @@ msgstr[3] "" #: data/json/items/melee/knives_kitchen.json msgid "butcher knife" msgid_plural "butcher knives" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ніж м'ясника" +msgstr[1] "ніж м'ясника" +msgstr[2] "ножів м'ясника" +msgstr[3] "ніж м'ясника" #. ~ Description for {'str': 'butcher knife', 'str_pl': 'butcher knives'} #: data/json/items/melee/knives_kitchen.json @@ -100930,10 +101262,10 @@ msgstr "" #: data/json/items/melee/knives_kitchen.json msgid "steak knife" msgid_plural "steak knives" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ніж для стейка" +msgstr[1] "ніж для стейка" +msgstr[2] "ножі для стейка" +msgstr[3] "ніж для стейка" #. ~ Description for {'str': 'steak knife', 'str_pl': 'steak knives'} #: data/json/items/melee/knives_kitchen.json @@ -101134,10 +101466,10 @@ msgstr "" #: data/json/items/melee/spears_and_polearms.json msgid "pitchfork" msgid_plural "pitchforks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "вили" +msgstr[1] "вил" +msgstr[2] "вил" +msgstr[3] "вила" #. ~ Description for {'str': 'pitchfork'} #: data/json/items/melee/spears_and_polearms.json @@ -101149,10 +101481,10 @@ msgstr "" #: data/json/items/melee/spears_and_polearms.json msgid "pointy stick" msgid_plural "pointy sticks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "загострена палка" +msgstr[1] "загострені палки" +msgstr[2] "загострених палок" +msgstr[3] "загострена палка" #. ~ Description for {'str': 'pointy stick'} #: data/json/items/melee/spears_and_polearms.json @@ -101223,10 +101555,10 @@ msgstr "" #: data/json/items/melee/spears_and_polearms.json msgid "knife spear" msgid_plural "knife spears" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "спис із наконечником" +msgstr[1] "списа із наконечником" +msgstr[2] "списів із наконечником" +msgstr[3] "спис із наконечником" #. ~ Description for {'str': 'knife spear'} #: data/json/items/melee/spears_and_polearms.json @@ -101296,10 +101628,10 @@ msgstr "" #: data/json/items/melee/spears_and_polearms.json msgid "steel spear" msgid_plural "steel spears" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сталевий спис" +msgstr[1] "сталевий спис" +msgstr[2] "сталеві списи" +msgstr[3] "сталевий спис" #. ~ Description for {'str': 'steel spear'} #: data/json/items/melee/spears_and_polearms.json @@ -101726,10 +102058,10 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "hunting knife" msgid_plural "hunting knives" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мисливський ніж" +msgstr[1] "мисливських ножа" +msgstr[2] "мисливських ножів" +msgstr[3] "мисливський ніж" #. ~ Description for {'str': 'hunting knife', 'str_pl': 'hunting knives'} #: data/json/items/melee/swords_and_blades.json @@ -101807,10 +102139,10 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "makeshift knife" msgid_plural "makeshift knives" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "саморобний ніж" +msgstr[1] "саморобний ніж" +msgstr[2] "саморобний ніж" +msgstr[3] "саморобні ножі" #. ~ Description for {'str': 'makeshift knife', 'str_pl': 'makeshift knives'} #: data/json/items/melee/swords_and_blades.json @@ -103480,10 +103812,10 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "compound bow" msgid_plural "compound bows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "блочний лук" +msgstr[1] "блочні луки" +msgstr[2] "блочних луків" +msgstr[3] "блочний лук" #: data/json/items/ranged/archery.json msgid "" @@ -103495,10 +103827,10 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "compound bow (high)" msgid_plural "compound bows (high)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "блочний лук (сильн.)" +msgstr[1] "блочні луки (сильн.)" +msgstr[2] "блочних луків (сильн.)" +msgstr[3] "блочний лук (сильн.)" #: data/json/items/ranged/archery.json msgid "" @@ -103510,10 +103842,10 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "compound bow (low)" msgid_plural "compound bows (low)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "блочний лук (легк.)" +msgstr[1] "блочні луки (легк.)" +msgstr[2] "блочних луків (легк.)" +msgstr[3] "блочний лук (легк.)" #: data/json/items/ranged/archery.json msgid "" @@ -103553,10 +103885,10 @@ msgstr "" #: data/json/items/ranged/archery.json msgid "longbow" msgid_plural "longbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "довгий лук" +msgstr[1] "довгий лук" +msgstr[2] "довгі луки" +msgstr[3] "довгий лук" #: data/json/items/ranged/archery.json msgid "" @@ -103800,10 +104132,10 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "bullet crossbow" msgid_plural "bullet crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кульовий арбалет" +msgstr[1] "кульових арбалети" +msgstr[2] "кульових арбалетів" +msgstr[3] "кульовий арбалет" #: data/json/items/ranged/crossbows.json msgid "" @@ -103815,10 +104147,10 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "pistol crossbow" msgid_plural "pistol crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "арбалет-пістолет" +msgstr[1] "арбалети-пістолети" +msgstr[2] "арбалетів-пістолетів" +msgstr[3] "арбалет-пістолет" #: data/json/items/ranged/crossbows.json msgid "" @@ -103830,10 +104162,10 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "crossbow" msgid_plural "crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "арбалет" +msgstr[1] "арбалети" +msgstr[2] "арбалетів" +msgstr[3] "арбалет" #: data/json/items/ranged/crossbows.json msgid "" @@ -103845,10 +104177,10 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "composite crossbow" msgid_plural "composite crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "композитний арбалет" +msgstr[1] "композитний арбалет" +msgstr[2] "композитних арбалетів" +msgstr[3] "композитний арбалет" #: data/json/items/ranged/crossbows.json msgid "" @@ -103859,10 +104191,10 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "compound crossbow" msgid_plural "compound crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "блочний арбалет" +msgstr[1] "блочні арбалети" +msgstr[2] "блочних арбалетів" +msgstr[3] "блочний арбалет" #: data/json/items/ranged/crossbows.json msgid "" @@ -103873,10 +104205,10 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "heavy crossbow" msgid_plural "heavy crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "важкий арбалет" +msgstr[1] "важких арбалети" +msgstr[2] "важких арбалетів" +msgstr[3] "важкий арбалет" #: data/json/items/ranged/crossbows.json msgid "" @@ -103889,10 +104221,10 @@ msgstr "" #: data/json/items/ranged/crossbows.json msgid "repeating crossbow" msgid_plural "repeating crossbows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "багатозарядний арбалет" +msgstr[1] "багатозарядних арбалети" +msgstr[2] "багатозарядних арбалетів" +msgstr[3] "багатозарядний арбалет" #: data/json/items/ranged/crossbows.json msgid "" @@ -104197,10 +104529,10 @@ msgstr "" #: data/json/items/ranged/throwing.json msgid "throwing knife" msgid_plural "throwing knives" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ніж для метання" +msgstr[1] "ножі для метання" +msgstr[2] "ножі для метання" +msgstr[3] "ножі для метання" #. ~ Description for {'str': 'throwing knife', 'str_pl': 'throwing knives'} #: data/json/items/ranged/throwing.json @@ -104402,10 +104734,10 @@ msgstr "" #: data/json/items/resources/glass.json msgid "glass shard" msgid_plural "glass shards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "уламок скла" +msgstr[1] "уламки скла" +msgstr[2] "уламків скла" +msgstr[3] "уламок скла" #. ~ Description for {'str': 'glass shard'} #: data/json/items/resources/glass.json @@ -104484,10 +104816,10 @@ msgstr "" #: data/json/items/resources/home_improvement.json msgid "red paint" msgid_plural "red paint" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "червона фарба" +msgstr[1] "червона фарба" +msgstr[2] "червона фарба" +msgstr[3] "червона фарба" #. ~ Description for {'str_sp': 'red paint'} #: data/json/items/resources/home_improvement.json @@ -104610,10 +104942,10 @@ msgstr "" #: data/json/items/resources/metal.json msgid "pipe" msgid_plural "pipes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "труба" +msgstr[1] "труби" +msgstr[2] "труб" +msgstr[3] "труба" #. ~ Description for {'str': 'pipe'} #: data/json/items/resources/metal.json @@ -104740,10 +105072,10 @@ msgstr "" #: data/json/items/resources/metal.json msgid "lead" msgid_plural "lead" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "свинець" +msgstr[1] "свинець" +msgstr[2] "свинець" +msgstr[3] "свинець" #. ~ Description for {'str_sp': 'lead'} #: data/json/items/resources/metal.json @@ -104772,10 +105104,10 @@ msgstr "" #: data/json/items/resources/metal.json msgid "silver" msgid_plural "silver" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "срібло" +msgstr[1] "срібло" +msgstr[2] "срібло" +msgstr[3] "срібло" #. ~ Description for {'str_sp': 'silver'} #: data/json/items/resources/metal.json @@ -104914,10 +105246,10 @@ msgstr "" #: data/json/items/resources/misc.json msgid "ceramic shard" msgid_plural "ceramic shards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "керамічний уламок" +msgstr[1] "керамічних уламки" +msgstr[2] "керамічних уламків" +msgstr[3] "керамічний уламок" #. ~ Description for {'str': 'ceramic shard'} #: data/json/items/resources/misc.json @@ -104982,10 +105314,10 @@ msgstr "" #: data/json/items/resources/misc.json msgid "sharp rock" msgid_plural "sharp rocks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "гострий камінь" +msgstr[1] "гострий камінь" +msgstr[2] "гострі камні" +msgstr[3] "гострі камні" #. ~ Description for {'str': 'sharp rock'} #: data/json/items/resources/misc.json @@ -105027,10 +105359,10 @@ msgstr "" #: data/json/items/resources/plastic.json msgid "plastic chunk" msgid_plural "plastic chunks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шматок пластмаси" +msgstr[1] "шматки пластмаси" +msgstr[2] "шматків пластмаси" +msgstr[3] "шматок пластмаси" #. ~ Description for {'str': 'plastic chunk'} #: data/json/items/resources/plastic.json @@ -105058,10 +105390,10 @@ msgstr "" #: data/json/items/resources/plastic.json msgid "plastic sheet" msgid_plural "plastic sheets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пластиковий лист" +msgstr[1] "пластикових листа" +msgstr[2] "пластикових листів" +msgstr[3] "пластиковий лист" #. ~ Description for {'str': 'plastic sheet'} #: data/json/items/resources/plastic.json @@ -105499,10 +105831,10 @@ msgstr "" #: data/json/items/resources/wood.json msgid "heavy stick" msgid_plural "heavy sticks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "товстий дрючок" +msgstr[1] "товстих дрючки" +msgstr[2] "товстих дрючків" +msgstr[3] "товстий дрючок" #. ~ Description for {'str': 'heavy stick'} #: data/json/items/resources/wood.json @@ -105512,10 +105844,10 @@ msgstr "" #: data/json/items/resources/wood.json msgid "long stick" msgid_plural "long sticks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "довга ломака" +msgstr[1] "довгі ломаки" +msgstr[2] "довгих ломак" +msgstr[3] "довга ломака" #. ~ Description for {'str': 'long stick'} #: data/json/items/resources/wood.json @@ -105542,10 +105874,10 @@ msgstr "" #: data/json/items/resources/wood.json src/crafting_gui.cpp msgid "plank" msgid_plural "planks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дошка" +msgstr[1] "дошки" +msgstr[2] "дошок" +msgstr[3] "дошка" #. ~ Description for {'str': 'plank'} #: data/json/items/resources/wood.json @@ -105726,10 +106058,10 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "charcoal water purifier" msgid_plural "charcoal water purifiers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "вугільний водоочисник" +msgstr[1] "вугільних водоочисника" +msgstr[2] "вугільних водоочисників" +msgstr[3] "вугільний водоочисник" #. ~ Description for {'str': 'charcoal water purifier'} #: data/json/items/tool/cooking.json @@ -105954,10 +106286,10 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "gasoline cooker" msgid_plural "gasoline cookers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бензиновий примус" +msgstr[1] "бензиновий примус" +msgstr[2] "бензинові примуси" +msgstr[3] "бензинові примуси" #. ~ Description for {'str': 'gasoline cooker'} #: data/json/items/tool/cooking.json @@ -105970,10 +106302,10 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "heat pack" msgid_plural "heat packs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "грілка" +msgstr[1] "грілка" +msgstr[2] "грілка" +msgstr[3] "грілки" #. ~ Description for {'str': 'heat pack'} #: data/json/items/tool/cooking.json @@ -106570,10 +106902,10 @@ msgstr "" #: data/json/items/tool/electronics.json msgid "cellphone" msgid_plural "cellphones" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сотовий телефон" +msgstr[1] "сотовий телефон" +msgstr[2] "сотовий телефон" +msgstr[3] "сотові телефони" #. ~ Use action msg for {'str': 'cellphone'}. #. ~ Use action msg for laptop computer. @@ -106765,10 +107097,10 @@ msgstr[3] "" #: data/json/items/tool/electronics.json msgid "mp3 player (off)" msgid_plural "mp3 players (off)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "mp3-плеєр (вимк)" +msgstr[1] "mp3-плеєра (вимк)" +msgstr[2] "mp3-плеєрів (вимк)" +msgstr[3] "mp3-плеєр (вимк)" #. ~ Description for {'str': 'mp3 player (off)', 'str_pl': 'mp3 players #. (off)'} @@ -106782,10 +107114,10 @@ msgstr "" #: data/json/items/tool/electronics.json msgid "mp3 player (on)" msgid_plural "mp3 players (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "mp3-плеєр (увімк)" +msgstr[1] "mp3-плеєра (увімк)" +msgstr[2] "mp3-плеєрів (увімк)" +msgstr[3] "mp3-плеєр (увімк)" #. ~ Description for {'str': 'mp3 player (on)', 'str_pl': 'mp3 players (on)'} #: data/json/items/tool/electronics.json @@ -106832,10 +107164,10 @@ msgstr "" #: data/json/items/tool/electronics.json msgid "handheld game system" msgid_plural "handheld game systems" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "портативна ігрова приставка" +msgstr[1] "портативних ігрових приставки" +msgstr[2] "портативних ігрових приставок" +msgstr[3] "портативна ігрова приставка" #. ~ Description for {'str': 'handheld game system'} #: data/json/items/tool/electronics.json @@ -106848,10 +107180,10 @@ msgstr "" #: data/json/items/tool/electronics.json msgid "smartphone" msgid_plural "smartphones" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "смартфон" +msgstr[1] "смартфона" +msgstr[2] "смартфонів" +msgstr[3] "смартфон" #. ~ Use action msg for {'str': 'smartphone'}. #. ~ Use action msg for {'str': 'atomic smartphone'}. @@ -106935,10 +107267,10 @@ msgstr "" #: data/json/items/tool/electronics.json msgid "vibrator" msgid_plural "vibrators" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "вібратор" +msgstr[1] "вібратора" +msgstr[2] "вібраторів" +msgstr[3] "вібратор" #. ~ Description for {'str': 'vibrator'} #: data/json/items/tool/electronics.json @@ -106991,10 +107323,10 @@ msgstr "" #: data/json/items/tool/entry_tools.json msgid "crowbar" msgid_plural "crowbars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ломик" +msgstr[1] "ломика" +msgstr[2] "ломиків" +msgstr[3] "ломик" #. ~ Description for {'str': 'crowbar'} #: data/json/items/tool/entry_tools.json @@ -107007,10 +107339,10 @@ msgstr "" #: data/json/items/tool/entry_tools.json msgid "improvised lockpick" msgid_plural "improvised lockpicks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "саморобна відмичка" +msgstr[1] "саморобна відмичка" +msgstr[2] "саморобні відмички" +msgstr[3] "саморобна відмичка" #. ~ Description for {'str': 'improvised lockpick'} #: data/json/items/tool/entry_tools.json @@ -107039,10 +107371,10 @@ msgstr "" #: data/json/items/tool/entry_tools.json msgid "makeshift crowbar" msgid_plural "makeshift crowbars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "саморобний ломик" +msgstr[1] "саморобних ломика" +msgstr[2] "саморобних ломиків" +msgstr[3] "саморобний ломик" #. ~ Description for {'str': 'makeshift crowbar'} #: data/json/items/tool/entry_tools.json @@ -107056,10 +107388,10 @@ msgstr "" #: data/json/items/tool/entry_tools.json msgid "locksmith kit" msgid_plural "locksmith kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "слюсарні відмички" +msgstr[1] "слюсарні відмички" +msgstr[2] "слюсарних відмичок" +msgstr[3] "слюсарні відмички" #. ~ Description for {'str': 'locksmith kit'} #: data/json/items/tool/entry_tools.json @@ -107187,10 +107519,10 @@ msgstr "" #: data/json/items/tool/explosives.json msgid "dynamite" msgid_plural "dynamites" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "динаміт" +msgstr[1] "динаміти" +msgstr[2] "динамітів" +msgstr[3] "динаміт" #. ~ Use action msg for {'str': 'dynamite'}. #. ~ Use action msg for {'str': 'dynamite bomb'}. @@ -107210,10 +107542,10 @@ msgstr "" #: data/json/items/tool/explosives.json msgid "dynamite (lit)" msgid_plural "dynamites (lit)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "динаміт (горить)" +msgstr[1] "динаміти (горить)" +msgstr[2] "динамітів (горить)" +msgstr[3] "динаміт (горить)" #. ~ Description for {'str': 'dynamite (lit)', 'str_pl': 'dynamites (lit)'} #: data/json/items/tool/explosives.json @@ -108210,10 +108542,10 @@ msgstr "" #: data/json/items/tool/fire.json msgid "lighter" msgid_plural "lighters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "запальничка" +msgstr[1] "запальничка" +msgstr[2] "запальнички" +msgstr[3] "запальничка" #. ~ Description for {'str': 'lighter'} #: data/json/items/tool/fire.json @@ -108226,10 +108558,10 @@ msgstr "" #: data/json/items/tool/fire.json msgid "magnifying glass" msgid_plural "magnifying glasses" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "збільшувальне скло" +msgstr[1] "збільшувальних скла" +msgstr[2] "збільшувальних стекол" +msgstr[3] "збільшувальне скло" #. ~ Description for {'str': 'magnifying glass', 'str_pl': 'magnifying #. glasses'} @@ -108244,10 +108576,10 @@ msgstr "" #: data/json/items/tool/fire.json msgid "matchbook" msgid_plural "matchbooks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "коробок сірників" +msgstr[1] "коробок сірників" +msgstr[2] "коробок сірників" +msgstr[3] "коробки сірників" #. ~ Description for {'str': 'matchbook'} #: data/json/items/tool/fire.json @@ -108261,10 +108593,10 @@ msgstr "" #: data/json/items/tool/fire.json msgid "refillable lighter" msgid_plural "refillable lighters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "запальничка багаторазова" +msgstr[1] "запальничка багаторазова" +msgstr[2] "запальнички багаторазові" +msgstr[3] "запальничка багаторазова" #. ~ Use action msg for {'str': 'refillable lighter'}. #: data/json/items/tool/fire.json @@ -108403,10 +108735,10 @@ msgstr "" #: data/json/items/tool/firefighting.json msgid "Halligan bar" msgid_plural "Halligan bars" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пожежний багор" +msgstr[1] "пожежних багра" +msgstr[2] "пожежних багрів" +msgstr[3] "пожежний багор" #. ~ Description for {'str': 'Halligan bar'} #: data/json/items/tool/firefighting.json @@ -108677,10 +109009,10 @@ msgstr "" #: data/json/items/tool/landscaping.json msgid "digging stick" msgid_plural "digging sticks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "палиця-копачка" +msgstr[1] "палиці-копачки" +msgstr[2] "палиць-копачок" +msgstr[3] "палиця-копачка" #. ~ Description for {'str': 'digging stick'} #: data/json/items/tool/landscaping.json @@ -108870,10 +109202,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "atomic reading light" msgid_plural "atomic reading lights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "атомна підсвітка для читання" +msgstr[1] "атомні підсвітки для читання" +msgstr[2] "атомних підсвіток для читання" +msgstr[3] "атомна підсвітка для читання" #. ~ Use action msg for {'str': 'atomic reading light'}. #. ~ Use action msg for magical reading light. @@ -108895,10 +109227,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "atomic reading light (covered)" msgid_plural "atomic reading lights (covered)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "атомна підсвітка для читання (накрите)" +msgstr[1] "атомні підсвітки для читання (накрите)" +msgstr[2] "атомних підсвіток для читання (накрите)" +msgstr[3] "атомна підсвітка для читання (накрите)" #. ~ Use action msg for {'str': 'atomic reading light (covered)', 'str_pl': #. 'atomic reading lights (covered)'}. @@ -109040,10 +109372,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "flashlight (on)" msgid_plural "flashlights (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ліхтарик (увімк.)" +msgstr[1] "ліхтарик (увімк.)" +msgstr[2] "ліхтарики (увімк.)" +msgstr[3] "ліхтарики (увімк.)" #. ~ Use action msg for {'str': 'flashlight (on)', 'str_pl': 'flashlights #. (on)'}. @@ -109054,10 +109386,10 @@ msgstr "Ви вимикаєте ліхтарик" #: data/json/items/tool/lighting.json msgid "gasoline lantern (off)" msgid_plural "gasoline lanterns (off)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бензиновый ліхтар (вимк)" +msgstr[1] "бензиновый ліхтар (вимк)" +msgstr[2] "бензинові ліхтарі (вимк)" +msgstr[3] "бензинові ліхтарі (вимк)" #. ~ Use action need_charges_msg for {'str': 'gasoline lantern (off)', #. 'str_pl': 'gasoline lanterns (off)'}. @@ -109080,10 +109412,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "gasoline lantern (on)" msgid_plural "gasoline lanterns (on)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бензиновий ліхтар (увімк)" +msgstr[1] "бензиновий ліхтар (увімк)" +msgstr[2] "бензинові ліхтарі (увімк)" +msgstr[3] "бензинові ліхтарі (увімк)" #. ~ Use action msg for {'str': 'gasoline lantern (on)', 'str_pl': 'gasoline #. lanterns (on)'}. @@ -109105,10 +109437,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "glowstick" msgid_plural "glowsticks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "хімічна паличка-ліхтарик" +msgstr[1] "хімічна паличка-ліхтарик" +msgstr[2] "хімічні палички-ліхтарики" +msgstr[3] "хімічна паличка-ліхтарик" #. ~ Use action msg for {'str': 'glowstick'}. #: data/json/items/tool/lighting.json @@ -109154,10 +109486,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "flare" msgid_plural "flares" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сигнальний фаєр" +msgstr[1] "сигнальний фаєр" +msgstr[2] "сигнальні фаєри" +msgstr[3] "сигнальний фаєр" #. ~ Use action menu_text for {'str': 'flare'}. #: data/json/items/tool/lighting.json @@ -109349,10 +109681,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "reading light" msgid_plural "reading lights" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "підсвітка для читання" +msgstr[1] "підсвітки для читання" +msgstr[2] "підсвіток для читання" +msgstr[3] "підсвітка для читання" #. ~ Use action msg for {'str': 'reading light'}. #: data/json/items/tool/lighting.json @@ -109374,10 +109706,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "reading light (active)" msgid_plural "reading lights (active)" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "підсвітка для читання (активна)" +msgstr[1] "підсвітки для читання (активна)" +msgstr[2] "підсвіток для читання (активна)" +msgstr[3] "підсвітка для читання (активна)" #. ~ Use action msg for {'str': 'reading light (active)', 'str_pl': 'reading #. lights (active)'}. @@ -109445,10 +109777,10 @@ msgstr "" #: data/json/items/tool/lighting.json msgid "torch" msgid_plural "torches" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "смолоскип" +msgstr[1] "смолоскипа" +msgstr[2] "смолоскипів" +msgstr[3] "смолоскип" #. ~ Use action menu_text for {'str': 'torch', 'str_pl': 'torches'}. #. ~ Use action menu_text for {'str': 'everburning torch', 'str_pl': @@ -109572,10 +109904,10 @@ msgstr "" #: data/json/items/tool/med.json msgid "inhaler" msgid_plural "inhalers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "інгалятор" +msgstr[1] "інгалятора" +msgstr[2] "інгаляторів" +msgstr[3] "інгалятори" #. ~ Description for {'str': 'inhaler'} #: data/json/items/tool/med.json @@ -109607,10 +109939,10 @@ msgstr "" #: data/json/items/tool/med.json msgid "scalpel" msgid_plural "scalpels" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "скальпель" +msgstr[1] "скальпелі" +msgstr[2] "скальпелів" +msgstr[3] "скальпель" #. ~ Description for {'str': 'scalpel'} #: data/json/items/tool/med.json @@ -109652,10 +109984,10 @@ msgstr "" #: data/json/items/tool/med.json msgid "thermometer" msgid_plural "thermometers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "термометр" +msgstr[1] "термометр" +msgstr[2] "термометри" +msgstr[3] "термометр" #. ~ Description for {'str': 'thermometer'} #: data/json/items/tool/med.json @@ -109746,10 +110078,10 @@ msgstr "" #: data/json/items/tool/metalworking.json msgid "pair of bolt cutters" msgid_plural "pairs of bolt cutters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "болторіз" +msgstr[1] "болторізи" +msgstr[2] "болторізів" +msgstr[3] "болторіз" #. ~ Description for {'str': 'pair of bolt cutters', 'str_pl': 'pairs of bolt #. cutters'} @@ -110160,10 +110492,10 @@ msgstr "" #: data/json/items/tool/misc.json msgid "flammable arrow" msgid_plural "flammable arrows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "запалювальна стріла" +msgstr[1] "запалювальні стріли" +msgstr[2] "запалювальних стріл" +msgstr[3] "запалювальні стріли" #. ~ Description for {'str': 'flammable arrow'} #: data/json/items/tool/misc.json @@ -110175,10 +110507,10 @@ msgstr "" #: data/json/items/tool/misc.json msgid "fur rollmat" msgid_plural "fur rollmats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "туристичний килимок із хутра" +msgstr[1] "туристичний килимок із хутра" +msgstr[2] "туристичний килимок із хутра" +msgstr[3] "туристичні килимки із хутра" #. ~ Use action done_message for {'str': 'fur rollmat'}. #: data/json/items/tool/misc.json @@ -110431,10 +110763,10 @@ msgstr "" #: data/json/items/tool/misc.json msgid "zombie pheromone" msgid_plural "zombie pheromones" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі феромон" +msgstr[1] "зомбі феромон" +msgstr[2] "зомбі феромонів" +msgstr[3] "зомбі феромон" #. ~ Description for {'str': 'zombie pheromone'} #: data/json/items/tool/misc.json @@ -110464,10 +110796,10 @@ msgstr "" #: data/json/items/tool/misc.json msgid "rollmat" msgid_plural "rollmats" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "туристичний килимок" +msgstr[1] "туристичний килимок" +msgstr[2] "туристичний килимок" +msgstr[3] "туристичні килимки" #. ~ Use action done_message for {'str': 'rollmat'}. #: data/json/items/tool/misc.json @@ -110576,10 +110908,10 @@ msgstr "" #: data/json/items/tool/misc.json msgid "survivor telescope" msgid_plural "survivor telescopes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "телескоп виживальника" +msgstr[1] "телескоп виживальника" +msgstr[2] "телескопи виживальника" +msgstr[3] "телескоп виживальника" #. ~ Description for {'str': 'survivor telescope'} #: data/json/items/tool/misc.json @@ -110838,10 +111170,10 @@ msgstr "" #: data/json/items/tool/pets.json msgid "dog whistle" msgid_plural "dog whistles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "собачий свисток" +msgstr[1] "собачих свистка" +msgstr[2] "собачих свистків" +msgstr[3] "собачий свисток" #. ~ Description for {'str': 'dog whistle'} #: data/json/items/tool/pets.json @@ -111738,10 +112070,10 @@ msgstr "" #: data/json/items/tool/smoking.json msgid "advanced electronic cigarette" msgid_plural "advanced electronic cigarettes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "покращена електронна цигарка" +msgstr[1] "покращені електронні цигарки" +msgstr[2] "покращених електронних цигарок" +msgstr[3] "покращена електронна цигарка" #. ~ Description for {'str': 'advanced electronic cigarette'} #: data/json/items/tool/smoking.json @@ -111925,10 +112257,10 @@ msgstr "" #: data/json/items/tool/tailoring.json msgid "wooden needle" msgid_plural "wooden needles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дерев'яна голка" +msgstr[1] "дерев'яна голка" +msgstr[2] "дерев'яна голка" +msgstr[3] "дерев'яні голки" #. ~ Description for {'str': 'wooden needle'} #: data/json/items/tool/tailoring.json @@ -111975,10 +112307,10 @@ msgstr "" #: data/json/items/tool/tailoring.json data/mods/Magiclysm/items/tools.json msgid "tailor's kit" msgid_plural "tailor's kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "набір кравця" +msgstr[1] "набори кравця" +msgstr[2] "наборів кравця" +msgstr[3] "набір кравця" #. ~ Description for {'str': "tailor's kit"} #: data/json/items/tool/tailoring.json @@ -112048,10 +112380,10 @@ msgstr "" #: data/json/items/tool/toiletries.json msgid "rag" msgid_plural "rags" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ганчірка" +msgstr[1] "ганчірка" +msgstr[2] "ганчірка" +msgstr[3] "ганчірки" #. ~ Description for {'str': 'rag'} #: data/json/items/tool/toiletries.json @@ -112076,10 +112408,10 @@ msgstr "" #: data/json/items/tool/toiletries.json msgid "shaving kit" msgid_plural "shaving kits" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "набір для гоління" +msgstr[1] "набори для гоління" +msgstr[2] "наборів для гоління" +msgstr[3] "набір для гоління" #. ~ Description for {'str': 'shaving kit'} #: data/json/items/tool/toiletries.json @@ -112766,10 +113098,10 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "electric jackhammer" msgid_plural "electric jackhammers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "електричний відбійний молоток" +msgstr[1] "електричні відбійні молотки" +msgstr[2] "електричних відбійних молотків" +msgstr[3] "електричний відбійний молоток" #. ~ Description for {'str': 'electric jackhammer'} #: data/json/items/tool/workshop.json @@ -112795,10 +113127,10 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "hammer" msgid_plural "hammers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "молоток" +msgstr[1] "молоток" +msgstr[2] "молотки" +msgstr[3] "молоток" #. ~ Description for {'str': 'hammer'} #: data/json/items/tool/workshop.json @@ -112884,10 +113216,10 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "jackhammer" msgid_plural "jackhammers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "відбійний молоток" +msgstr[1] "відбійні молотки" +msgstr[2] "відбійних молотків" +msgstr[3] "відбійний молоток" #. ~ Description for {'str': 'jackhammer'} #: data/json/items/tool/workshop.json @@ -112951,10 +113283,10 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "makeshift hammer" msgid_plural "makeshift hammers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "саморобний молоток" +msgstr[1] "саморобних молотка" +msgstr[2] "саморобних молотків" +msgstr[3] "саморобний молоток" #. ~ Description for {'str': 'makeshift hammer'} #: data/json/items/tool/workshop.json @@ -113028,10 +113360,10 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "multi-tool" msgid_plural "multi-tools" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мультитул" +msgstr[1] "мультитули" +msgstr[2] "мультитулів" +msgstr[3] "мультитул" #. ~ Description for {'str': 'multi-tool'} #: data/json/items/tool/workshop.json @@ -113135,10 +113467,10 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "stone hammer" msgid_plural "stone hammers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кам'яний молоток" +msgstr[1] "кам'яних молотки" +msgstr[2] "кам'яних молотків" +msgstr[3] "кам'яний молоток" #. ~ Description for {'str': 'stone hammer'} #: data/json/items/tool/workshop.json @@ -113199,10 +113531,10 @@ msgstr "" #: data/json/items/tool/workshop.json src/crafting_gui.cpp msgid "soldering iron" msgid_plural "soldering irons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "паяльник" +msgstr[1] "паяльника" +msgstr[2] "паяльників" +msgstr[3] "паяльник" #. ~ Description for {'str': 'soldering iron'} #: data/json/items/tool/workshop.json @@ -113215,10 +113547,10 @@ msgstr "" #: data/json/items/tool/workshop.json msgid "toolbox" msgid_plural "toolboxes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "ящик з інструментами" +msgstr[1] "ящика з інструментами" +msgstr[2] "ящиків з інструментами" +msgstr[3] "ящик з інструментами" #. ~ Description for {'str': 'toolbox', 'str_pl': 'toolboxes'} #: data/json/items/tool/workshop.json @@ -113532,10 +113864,10 @@ msgstr "" #: data/json/items/vehicle/battery.json data/json/vehicleparts/battery.json msgid "motorbike battery" msgid_plural "motorbike batteries" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "мотоаккумулятор" +msgstr[1] "мотоаккумулятори" +msgstr[2] "мотоаккумуляторів" +msgstr[3] "мотоаккумулятор" #. ~ Description for {'str': 'motorbike battery', 'str_pl': 'motorbike #. batteries'} @@ -113742,10 +114074,10 @@ msgstr "" #: data/json/vehicleparts/vehicle_parts.json msgid "jumper cable" msgid_plural "jumper cables" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "з'єднувальний кабель" +msgstr[1] "з'єднувальні кабелі" +msgstr[2] "з'єднувальних кабелів" +msgstr[3] "з'єднувальний кабель" #. ~ Description for {'str': 'jumper cable'} #: data/json/items/vehicle/cables.json @@ -114670,10 +115002,10 @@ msgstr "" #: data/json/items/vehicle/frames.json msgid "foldable-light frame" msgid_plural "foldable-light frames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "складна полегшена рама" +msgstr[1] "складні полегшені рами" +msgstr[2] "складних полегшених рам" +msgstr[3] "складна полегшена рама" #. ~ Description for {'str': 'foldable-light frame'} #: data/json/items/vehicle/frames.json @@ -114683,10 +115015,10 @@ msgstr "" #: data/json/items/vehicle/frames.json msgid "extra-light frame" msgid_plural "extra-light frames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "полегшена рама" +msgstr[1] "полегшені рами" +msgstr[2] "полегшених рам" +msgstr[3] "полегшена рама" #. ~ Description for {'str': 'extra-light frame'} #: data/json/items/vehicle/frames.json @@ -114696,10 +115028,10 @@ msgstr "" #: data/json/items/vehicle/frames.json msgid "steel frame" msgid_plural "steel frames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "сталева рама" +msgstr[1] "сталеві рами" +msgstr[2] "сталевих рам" +msgstr[3] "сталева рама" #. ~ Description for {'str': 'steel frame'} #: data/json/items/vehicle/frames.json @@ -114709,10 +115041,10 @@ msgstr "" #: data/json/items/vehicle/frames.json data/json/vehicleparts/frames.json msgid "heavy duty frame" msgid_plural "heavy duty frames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зміцнена рама" +msgstr[1] "зміцнені рами" +msgstr[2] "зміцнених рам" +msgstr[3] "зміцнена рама" #. ~ Description for {'str': 'heavy duty frame'} #: data/json/items/vehicle/frames.json @@ -114723,10 +115055,10 @@ msgstr "" #: data/json/items/vehicle/frames.json data/json/vehicleparts/frames.json msgid "wooden frame" msgid_plural "wooden frames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "дерев'яна рама" +msgstr[1] "дерев'яні рами" +msgstr[2] "дерев'яних рам" +msgstr[3] "дерев'яна рама" #. ~ Description for {'str': 'wooden frame'} #: data/json/items/vehicle/frames.json @@ -114736,10 +115068,10 @@ msgstr "" #: data/json/items/vehicle/frames.json data/json/vehicleparts/frames.json msgid "foldable wooden frame" msgid_plural "foldable wooden frames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "складна дерев'яна рама" +msgstr[1] "складні дерев'яні рами" +msgstr[2] "складних дерев'яних рам" +msgstr[3] "складна дерев'яна рама" #. ~ Description for {'str': 'foldable wooden frame'} #: data/json/items/vehicle/frames.json @@ -114749,10 +115081,10 @@ msgstr "" #: data/json/items/vehicle/frames.json data/json/vehicleparts/frames.json msgid "light wooden frame" msgid_plural "light wooden frames" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "легка дерев'яна рама" +msgstr[1] "легкі дерев'яні рами" +msgstr[2] "легких дерев'яних рам" +msgstr[3] "легка дерев'яна рама" #. ~ Description for {'str': 'light wooden frame'} #: data/json/items/vehicle/frames.json @@ -115844,10 +116176,10 @@ msgstr "" #: data/json/vehicleparts/vehicle_parts.json msgid "water faucet" msgid_plural "water faucets" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "водопровідний кран" +msgstr[1] "водопровідних крана" +msgstr[2] "водопровідних кранів" +msgstr[3] "водопровідний кран" #. ~ Description for {'str': 'water faucet'} #: data/json/items/vehicle/utilities.json @@ -117863,10 +118195,10 @@ msgstr "" #: data/json/monsters/bird.json msgid "pheasant" msgid_plural "pheasants" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "фазан" +msgstr[1] "фазани" +msgstr[2] "фазанів" +msgstr[3] "фазан" #. ~ Description for {'str': 'pheasant'} #: data/json/monsters/bird.json @@ -119451,10 +119783,10 @@ msgstr "" #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal zombie" msgid_plural "fungal zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "грибо-зомбі" +msgstr[1] "грибо-зомбі" +msgstr[2] "грибо-зомбі" +msgstr[3] "грибо-зомбі" #. ~ Description for {'str': 'fungal zombie'} #: data/json/monsters/fungus.json @@ -119466,10 +119798,10 @@ msgstr "" #: data/json/monsters/fungus.json msgid "bloated fungal zombie" msgid_plural "bloated fungal zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "роздутий грибо-зомбі" +msgstr[1] "роздуті грибо-зомбі" +msgstr[2] "роздутих грибо-зомбі" +msgstr[3] "роздутий грибо-зомбі" #. ~ Description for {'str': 'bloated fungal zombie'} #: data/json/monsters/fungus.json @@ -119482,10 +119814,10 @@ msgstr "" #: data/json/monsters/fungus.json msgid "pollinator zombie" msgid_plural "pollinator zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-запилювач" +msgstr[1] "зомбі-запилювачі" +msgstr[2] "зомбі-запилювачів" +msgstr[3] "зомбі-запилювач" #. ~ Description for {'str': 'pollinator zombie'} #: data/json/monsters/fungus.json @@ -122454,14 +122786,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -123020,10 +123344,10 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "zombie dog" msgid_plural "zombie dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-собака" +msgstr[1] "зомбі-собаки" +msgstr[2] "зомбі-собак" +msgstr[3] "зомбі-собака" #. ~ Description for {'str': 'zombie dog'} #: data/json/monsters/zed-animal.json @@ -123035,10 +123359,10 @@ msgstr "" #: data/json/monsters/zed-animal.json msgid "skeletal dog" msgid_plural "skeletal dogs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "собака-скелет" +msgstr[1] "собаки-скелети" +msgstr[2] "собак-скелетів" +msgstr[3] "собака-скелет" #. ~ Description for {'str': 'skeletal dog'} #: data/json/monsters/zed-animal.json @@ -123177,10 +123501,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "scarred zombie" msgid_plural "scarred zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "вкритий шрамами зомбі" +msgstr[1] "вкритих шрамами зомбі" +msgstr[2] "вкритих шрамами зомбі" +msgstr[3] "вкритий шрамами зомбі" #. ~ Description for {'str': 'scarred zombie'} #: data/json/monsters/zed-classic.json @@ -123189,14 +123513,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -123207,10 +123523,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "zombie cop" msgid_plural "zombie cops" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-поліціянт" +msgstr[1] "зомбі-поліціянти" +msgstr[2] "зомбі-поліціянтів" +msgstr[3] "зомбі-поліціянт" #. ~ Description for {'str': 'zombie cop'} #: data/json/monsters/zed-classic.json @@ -123221,10 +123537,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "crawling zombie" msgid_plural "crawling zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-повзун" +msgstr[1] "зомбі-повзуни" +msgstr[2] "зомбі-повзунів" +msgstr[3] "зомбі-повзун" #. ~ Description for {'str': 'crawling zombie'} #: data/json/monsters/zed-classic.json @@ -123236,10 +123552,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "zombie dancer" msgid_plural "zombie dancers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-танцюрист" +msgstr[1] "зомбі-танцюристи" +msgstr[2] "зомбі-танцюристів" +msgstr[3] "зомбі-танцюрист" #. ~ Description for {'str': 'zombie dancer'} #: data/json/monsters/zed-classic.json @@ -123255,10 +123571,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "fat zombie" msgid_plural "fat zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "гладкий зомбі" +msgstr[1] "гладкі зомбі" +msgstr[2] "гладких зомбі" +msgstr[3] "гладкий зомбі" #. ~ Description for {'str': 'fat zombie'} #: data/json/monsters/zed-classic.json @@ -123270,10 +123586,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "firefighter zombie" msgid_plural "firefighter zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-пожежник" +msgstr[1] "зомбі-пожежника" +msgstr[2] "зомбі-пожежників" +msgstr[3] "зомбі-пожежник" #. ~ Description for {'str': 'firefighter zombie'} #: data/json/monsters/zed-classic.json @@ -123285,10 +123601,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "hazmat zombie" msgid_plural "hazmat zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі у хімзахисті" +msgstr[1] "зомбі у хімзахисті" +msgstr[2] "зомбі у хімзахисті" +msgstr[3] "зомбі у хімзахисті" #. ~ Description for {'str': 'hazmat zombie'} #: data/json/monsters/zed-classic.json @@ -123300,10 +123616,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "decayed zombie" msgid_plural "decayed zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "гнилий зомбі" +msgstr[1] "гнилі зомбі" +msgstr[2] "гнилих зомбі" +msgstr[3] "гнилий зомбі" #. ~ Description for {'str': 'decayed zombie'} #: data/json/monsters/zed-classic.json @@ -123330,10 +123646,10 @@ msgstr "" #: data/json/monsters/zed-classic.json msgid "tough zombie" msgid_plural "tough zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-здоровань" +msgstr[1] "зомбі-здорованя" +msgstr[2] "зомбі-здорованів" +msgstr[3] "зомбі-здоровань" #. ~ Description for {'str': 'tough zombie'} #: data/json/monsters/zed-classic.json @@ -123373,10 +123689,10 @@ msgstr "" #: data/json/monsters/zed_acid.json msgid "acidic zombie" msgid_plural "acidic zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "кислотний зомбі" +msgstr[1] "кислотних зомбі" +msgstr[2] "кислотних зомбі" +msgstr[3] "кислотний зомбі" #. ~ Description for {'str': 'acidic zombie'} #: data/json/monsters/zed_acid.json @@ -123388,10 +123704,10 @@ msgstr "" #: data/json/monsters/zed_acid.json msgid "corrosive zombie" msgid_plural "corrosive zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "корозійний зомбі" +msgstr[1] "корозійні зомбі" +msgstr[2] "корозійних зомбі" +msgstr[3] "корозійний зомбі" #. ~ Description for {'str': 'corrosive zombie'} #: data/json/monsters/zed_acid.json @@ -123408,10 +123724,10 @@ msgstr "Корозійний зомбі випльовує згусток кис #: data/json/monsters/zed_acid.json msgid "spitter zombie" msgid_plural "spitter zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-плювач" +msgstr[1] "зомбі-плювачі" +msgstr[2] "зомбі-плювачів" +msgstr[3] "зомбі-плювач" #. ~ Description for {'str': 'spitter zombie'} #: data/json/monsters/zed_acid.json @@ -123440,10 +123756,10 @@ msgstr "" #: data/json/monsters/zed_burned.json msgid "zombie kinderling" msgid_plural "zombie kinderlings" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-обгорільчик" +msgstr[1] "зомбі-обгорільчика" +msgstr[2] "зомбі-обгорільчиків" +msgstr[3] "зомбі-обгорільчик" #. ~ Description for {'str': 'zombie kinderling'} #: data/json/monsters/zed_burned.json @@ -123471,10 +123787,10 @@ msgstr "" #: data/json/monsters/zed_burned.json msgid "scorched zombie" msgid_plural "scorched zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "опалений зомбі" +msgstr[1] "опалені зомбі" +msgstr[2] "опалених зомбі" +msgstr[3] "опалений зомбі" #. ~ Description for {'str': 'scorched zombie'} #: data/json/monsters/zed_burned.json @@ -123501,10 +123817,10 @@ msgstr "" #: data/json/monsters/zed_children.json msgid "zombie child" msgid_plural "zombie children" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-дитина" +msgstr[1] "зомбі-дитини" +msgstr[2] "зомбі-дітей" +msgstr[3] "зомбі-дитина" #. ~ Description for {'str': 'zombie child', 'str_pl': 'zombie children'} #: data/json/monsters/zed_children.json @@ -123547,10 +123863,10 @@ msgstr "" #: data/json/monsters/zed_children.json msgid "snotgobbler" msgid_plural "snotgobblers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "соплеглот" +msgstr[1] "соплеглоти" +msgstr[2] "соплеглотів" +msgstr[3] "соплеглот" #. ~ Description for {'str': 'snotgobbler'} #: data/json/monsters/zed_children.json @@ -123610,10 +123926,10 @@ msgstr "" #: data/mods/CrazyCataclysm/crazy_monsters.json msgid "shocker zombie" msgid_plural "shocker zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-шокер" +msgstr[1] "зомбі-шокери" +msgstr[2] "зомбі-шокерів" +msgstr[3] "зомбі-шокер" #. ~ Description for {'str': 'shocker zombie'} #: data/json/monsters/zed_electric.json @@ -123685,10 +124001,10 @@ msgstr "" #: data/json/monsters/zed_explosive.json msgid "gasoline zombie" msgid_plural "gasoline zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "бензиновий зомбі" +msgstr[1] "бензинові зомбі" +msgstr[2] "бензинових зомбі" +msgstr[3] "бензиновий зомбі" #. ~ Description for {'str': 'gasoline zombie'} #: data/json/monsters/zed_explosive.json @@ -123702,10 +124018,10 @@ msgstr "" #: data/json/monsters/zed_explosive.json msgid "bloated zombie" msgid_plural "bloated zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "роздутий зомбі" +msgstr[1] "роздутих зомбі" +msgstr[2] "роздутих зомбі" +msgstr[3] "роздутий зомбі" #. ~ Description for {'str': 'bloated zombie'} #: data/json/monsters/zed_explosive.json @@ -123718,10 +124034,10 @@ msgstr "" #: data/json/monsters/zed_explosive.json msgid "zombie grenadier" msgid_plural "zombie grenadiers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-гренадер" +msgstr[1] "зомбі-гренадери" +msgstr[2] "зомбі-гренадерів" +msgstr[3] "зомбі-гренадер" #. ~ Description for {'str': 'zombie grenadier'} #: data/json/monsters/zed_explosive.json @@ -123733,10 +124049,10 @@ msgstr "" #: data/json/monsters/zed_explosive.json msgid "zombie elite grenadier" msgid_plural "zombie elite grenadiers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "елітний зомбі-гренадер" +msgstr[1] "елітні зомбі-гренадери" +msgstr[2] "елітних зомбі-гренадерів" +msgstr[3] "елітний зомбі-гренадер" #. ~ Description for {'str': 'zombie elite grenadier'} #: data/json/monsters/zed_explosive.json @@ -123863,10 +124179,10 @@ msgstr "" #: data/json/monsters/zed_lab.json msgid "zombie scientist" msgid_plural "zombie scientists" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-вчений" +msgstr[1] "зомбі-вчені" +msgstr[2] "зомбі-вчених" +msgstr[3] "зомбі-вчений" #. ~ Description for {'str': 'zombie scientist'} #: data/json/monsters/zed_lab.json @@ -123880,10 +124196,10 @@ msgstr "" #: data/json/monsters/zed_lab.json msgid "zombie security guard" msgid_plural "zombie security guards" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-охоронець" +msgstr[1] "зомбі-охоронця" +msgstr[2] "зомбі-охоронців" +msgstr[3] "зомбі-охоронець" #. ~ Description for {'str': 'zombie security guard'} #: data/json/monsters/zed_lab.json @@ -123961,10 +124277,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "brainless zombie" msgid_plural "brainless zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "безмозкий зомбі" +msgstr[1] "безмозких зомбі" +msgstr[2] "безмозких зомбі" +msgstr[3] "безмозкий зомбі" #. ~ Description for {'str': 'brainless zombie'} #: data/json/monsters/zed_misc.json @@ -123978,10 +124294,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie brute" msgid_plural "zombie brutes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-амбал" +msgstr[1] "зомбі-амбали" +msgstr[2] "зомбі-амбалів" +msgstr[3] "зомбі-амбал" #. ~ Description for {'str': 'zombie brute'} #: data/json/monsters/zed_misc.json @@ -123992,10 +124308,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie wrestler" msgid_plural "zombie wrestlers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-борець" +msgstr[1] "зомбі-борця" +msgstr[2] "зомбі-борців" +msgstr[3] "зомбі-борець" #. ~ Description for {'str': 'zombie wrestler'} #: data/json/monsters/zed_misc.json @@ -124007,10 +124323,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie nightstalker" msgid_plural "zombie nightstalkers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "нічний зомбі-ловчий" +msgstr[1] "нічні зомбі-ловчі" +msgstr[2] "нічних зомбі-ловчих" +msgstr[3] "нічний зомбі-ловчий" #. ~ Description for {'str': 'zombie nightstalker'} #: data/json/monsters/zed_misc.json @@ -124022,10 +124338,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "listener zombie" msgid_plural "listener zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-слухач" +msgstr[1] "зомбі-слухачі" +msgstr[2] "зомбі-слухачів" +msgstr[3] "зомбі-слухач" #. ~ Description for {'str': 'listener zombie'} #: data/json/monsters/zed_misc.json @@ -124039,10 +124355,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "grabber zombie" msgid_plural "grabber zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-обіймач" +msgstr[1] "зомбі-обіймачі" +msgstr[2] "зомбі-обіймачів" +msgstr[3] "зомбі-обіймач" #. ~ Description for {'str': 'grabber zombie'} #: data/json/monsters/zed_misc.json @@ -124054,10 +124370,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "grappler zombie" msgid_plural "grappler zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-хапальник" +msgstr[1] "зомбі-хапальники" +msgstr[2] "зомбі-хапальників" +msgstr[3] "зомбі-хапальник" #. ~ Description for {'str': 'grappler zombie'} #: data/json/monsters/zed_misc.json @@ -124070,10 +124386,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie hollow" msgid_plural "zombie hollows" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пустозомбі" +msgstr[1] "пустозомбі" +msgstr[2] "пустозомбі" +msgstr[3] "пустозомбі" #. ~ Description for {'str': 'zombie hollow'} #: data/json/monsters/zed_misc.json @@ -124088,10 +124404,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie hulk" msgid_plural "zombie hulks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-халк" +msgstr[1] "зомбі-халки" +msgstr[2] "зомбі-халків" +msgstr[3] "зомбі-халк" #. ~ Description for {'str': 'zombie hulk'} #: data/json/monsters/zed_misc.json @@ -124135,10 +124451,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie snapper" msgid_plural "zombie snappers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-кусач" +msgstr[1] "зомбі-кусачі" +msgstr[2] "зомбі-кусачів" +msgstr[3] "зомбі-кусач" #. ~ Description for {'str': 'zombie snapper'} #: data/json/monsters/zed_misc.json @@ -124150,10 +124466,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie master" msgid_plural "zombie masters" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-володар" +msgstr[1] "зомбі-володаря" +msgstr[2] "зомбі-володарів" +msgstr[3] "зомбі-володар" #. ~ Description for {'str': 'zombie master'} #: data/json/monsters/zed_misc.json @@ -124168,10 +124484,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie necromancer" msgid_plural "zombie necromancers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-некромант" +msgstr[1] "зомбі-некроманти" +msgstr[2] "зомбі-некромантів" +msgstr[3] "зомбі-некромант" #. ~ Description for {'str': 'zombie necromancer'} #: data/json/monsters/zed_misc.json @@ -124217,10 +124533,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "screecher zombie" msgid_plural "screecher zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-верескун" +msgstr[1] "зомбі-верескуни" +msgstr[2] "зомбі-верескунів" +msgstr[3] "зомбі-верескун" #. ~ Description for {'str': 'screecher zombie'} #: data/json/monsters/zed_misc.json @@ -124232,10 +124548,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "shady zombie" msgid_plural "shady zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "тіньовий зомбі" +msgstr[1] "тіньові зомбі" +msgstr[2] "тіньових зомбі" +msgstr[3] "тіньовий зомбі" #. ~ Description for {'str': 'shady zombie'} #: data/json/monsters/zed_misc.json @@ -124265,10 +124581,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "shrieker zombie" msgid_plural "shrieker zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-крикун" +msgstr[1] "зомбі-крикуни" +msgstr[2] "зомбі-крикунів" +msgstr[3] "зомбі-крикун" #. ~ Description for {'str': 'shrieker zombie'} #: data/json/monsters/zed_misc.json @@ -124280,10 +124596,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "skull zombie" msgid_plural "skull zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-череп" +msgstr[1] "зомбі-черепи" +msgstr[2] "зомбі-черепів" +msgstr[3] "зомбі-череп" #. ~ Description for {'str': 'skull zombie'} #: data/json/monsters/zed_misc.json @@ -124298,10 +124614,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "smoker zombie" msgid_plural "smoker zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-курець" +msgstr[1] "зомбі-курці" +msgstr[2] "зомбі-курців" +msgstr[3] "зомбі-курець" #. ~ Description for {'str': 'smoker zombie'} #: data/json/monsters/zed_misc.json @@ -124313,10 +124629,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "swimmer zombie" msgid_plural "swimmer zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-плавець" +msgstr[1] "зомбі-плавця" +msgstr[2] "зомбі-плавців" +msgstr[3] "зомбі-плавець" #. ~ Description for {'str': 'swimmer zombie'} #: data/json/monsters/zed_misc.json @@ -124328,10 +124644,10 @@ msgstr "" #: data/json/monsters/zed_misc.json msgid "zombie technician" msgid_plural "zombie technicians" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-технік" +msgstr[1] "зомбі-техніка" +msgstr[2] "зомбі-техніків" +msgstr[3] "зомбі-технік" #. ~ Description for {'str': 'zombie technician'} #: data/json/monsters/zed_misc.json @@ -124375,10 +124691,10 @@ msgstr "" #: data/json/monsters/zed_prisoner.json msgid "prisoner zombie" msgid_plural "prisoner zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-в'язень" +msgstr[1] "зомбі-в'язня" +msgstr[2] "зомбі-в'язнів" +msgstr[3] "зомбі-в'язень" #. ~ Description for {'str': 'prisoner zombie'} #: data/json/monsters/zed_prisoner.json @@ -124421,10 +124737,10 @@ msgstr "" #: data/json/monsters/zed_skeletal.json msgid "skeleton" msgid_plural "skeletons" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "скелет" +msgstr[1] "скелети" +msgstr[2] "скелетів" +msgstr[3] "скелет" #. ~ Description for {'str': 'skeleton'} #: data/json/monsters/zed_skeletal.json @@ -124438,10 +124754,10 @@ msgstr "" #: data/json/monsters/zed_skeletal.json msgid "skeletal brute" msgid_plural "skeletal brutes" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "амбал-скелет" +msgstr[1] "амбали-скелети" +msgstr[2] "амбалів-скелетів" +msgstr[3] "амбал-скелет" #. ~ Description for {'str': 'skeletal brute'} #: data/json/monsters/zed_skeletal.json @@ -124453,10 +124769,10 @@ msgstr "" #: data/json/monsters/zed_skeletal.json msgid "skeletal shocker" msgid_plural "skeletal shockers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "шокер-скелет" +msgstr[1] "шокери-скелети" +msgstr[2] "шокерів-скелетів" +msgstr[3] "шокер-скелет" #. ~ Description for {'str': 'skeletal shocker'} #: data/json/monsters/zed_skeletal.json @@ -124469,10 +124785,10 @@ msgstr "" #: data/json/monsters/zed_skeletal.json msgid "skeletal juggernaut" msgid_plural "skeletal juggernauts" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "скелет-джаггернаут" +msgstr[1] "скелети-джаггернаути" +msgstr[2] "скелетів-джаггернаутів" +msgstr[3] "скелет-джаггернаут" #. ~ Description for {'str': 'skeletal juggernaut'} #: data/json/monsters/zed_skeletal.json @@ -124486,10 +124802,10 @@ msgstr "" #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json msgid "zombie soldier" msgid_plural "zombie soldiers" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-солдат" +msgstr[1] "зомбі-солдата" +msgstr[2] "зомбі-солдатів" +msgstr[3] "зомбі-солдат" #. ~ Description for {'str': 'zombie soldier'} #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json @@ -124501,10 +124817,10 @@ msgstr "" #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json msgid "black-ops zombie" msgid_plural "black-ops zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі оперативник" +msgstr[1] "зомбі оперативника" +msgstr[2] "зомбі оперативників" +msgstr[3] "зомбі оперативник" #. ~ Description for {'str': 'black-ops zombie'} #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json @@ -124604,10 +124920,10 @@ msgstr "" #: data/json/monsters/zed_soldiers.json msgid "zombie military pilot" msgid_plural "zombie military pilots" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі військовий пілот" +msgstr[1] "зомбі військові пілоти" +msgstr[2] "зомбі військових пілотів" +msgstr[3] "зомбі військовий пілот" #. ~ Description for {'str': 'zombie military pilot'} #: data/json/monsters/zed_soldiers.json @@ -124652,10 +124968,10 @@ msgstr "" #: data/json/monsters/zed_soldiers.json msgid "zombie bio-operator" msgid_plural "zombie bio-operators" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-біооператор" +msgstr[1] "зомбі-біооператори" +msgstr[2] "зомбі-біооператорів" +msgstr[3] "зомбі-біооператор" #. ~ Description for {'str': 'zombie bio-operator'} #: data/json/monsters/zed_soldiers.json @@ -124682,10 +124998,10 @@ msgstr "" #: data/json/monsters/zed_survivor.json msgid "survivor zombie" msgid_plural "survivor zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "зомбі-виживальник" +msgstr[1] "зомбі-виживальника" +msgstr[2] "зомбі-виживальників" +msgstr[3] "зомбі-виживальник" #. ~ Description for {'str': 'survivor zombie'} #: data/json/monsters/zed_survivor.json @@ -133522,7 +133838,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -141338,10 +141655,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -154682,6 +154995,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -154718,6 +155041,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -157849,10 +158186,10 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Items/tools.json msgid "No. 9" msgid_plural "No. 9's" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "№9" +msgstr[1] "№9" +msgstr[2] "№9" +msgstr[3] "№9" #. ~ Use action failure_message for {'str': 'No. 9', 'str_pl': "No. 9's"}. #. ~ Use action lacks_fuel_message for {'str': 'No. 9', 'str_pl': "No. 9's"}. @@ -158421,10 +158758,10 @@ msgstr "" #: data/json/obsoletion/items.json msgid "coilgun" msgid_plural "coilguns" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "Гаус-гармата" +msgstr[1] "Гаус-гармати" +msgstr[2] "Гаус-гармат" +msgstr[3] "Гаус-гармата" #: data/json/obsoletion/items.json msgid "" @@ -158435,10 +158772,10 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Items/guns.json msgid "nail rifle" msgid_plural "nail rifles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "цвяхостріл" +msgstr[1] "цвяхостріли" +msgstr[2] "цвяхострілів" +msgstr[3] "цвяхостріл" #: data/json/obsoletion/items.json data/mods/No_Hope/Items/guns.json msgid "" @@ -159157,10 +159494,10 @@ msgstr "" #: data/json/obsoletion/items.json msgid "pool ball" msgid_plural "pool balls" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "більярдна куля" +msgstr[1] "більярдні кулі" +msgstr[2] "більярдних куль" +msgstr[3] "більярдна куля" #. ~ Description for {'str': 'pool ball'} #: data/json/obsoletion/items.json @@ -159675,10 +160012,10 @@ msgstr "" #: data/json/obsoletion/items.json msgid "butchery refuse" msgid_plural "butchery refuse" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "відходи від патрання" +msgstr[1] "відходи від патрання" +msgstr[2] "відходи від патрання" +msgstr[3] "відходи від патрання" #. ~ Description for {'str_sp': 'butchery refuse'} #: data/json/obsoletion/items.json @@ -160870,10 +161207,10 @@ msgstr "" #: data/json/obsoletion/items.json msgid "test tube rack" msgid_plural "test tube racks" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "стійка для пробірок" +msgstr[1] "стійки для пробірок" +msgstr[2] "стійок для пробірок" +msgstr[3] "стійка для пробірок" #. ~ Description for {'str': 'test tube rack'} #: data/json/obsoletion/items.json @@ -181999,10 +182336,10 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "USMC M1014 technical manual" msgid_plural "USMC M1014 technical manuals" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "технічний посібник КМПС М1014" +msgstr[1] "технічний посібник КМПС М1014" +msgstr[2] "технічні посібники КМПС М1014" +msgstr[3] "технічні посібники КМПС М1014" #. ~ Description for {'str': 'USMC M1014 technical manual'} #: data/mods/Aftershock/items/books.json @@ -185591,6 +185928,15 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -185664,10 +186010,10 @@ msgstr "" #: data/mods/Aftershock/mobs/zombies.json msgid "headless zombie" msgid_plural "headless zombies" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "безголовий зомбі" +msgstr[1] "безголові зомбі" +msgstr[2] "безголових зомбі" +msgstr[3] "безголовий зомбі" #. ~ Description for {'str': 'headless zombie'} #: data/mods/Aftershock/mobs/zombies.json @@ -189732,10 +190078,10 @@ msgstr "" #: data/mods/CRT_EXPANSION/items/crt_generic.json msgid "withered plant bundle" msgid_plural "withered plant bundles" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" +msgstr[0] "пучок зів'ялих рослин" +msgstr[1] "пучки зів'ялих рослин" +msgstr[2] "пучків зів'ялих рослин" +msgstr[3] "пучок зів'ялих рослин" #. ~ Description for withered plant bundle #: data/mods/CRT_EXPANSION/items/crt_generic.json @@ -196008,6 +196354,15 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -209578,6 +209933,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -209705,6 +210065,30 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -213802,6 +214186,22 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -214075,6 +214475,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -214083,6 +214484,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -214155,6 +214557,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -214163,6 +214566,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -214394,6 +214798,22 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -215400,6 +215820,102 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -216656,6 +217172,22 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -217983,6 +218515,14 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -218000,14 +218540,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -221102,10 +221634,26 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -223543,6 +224091,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -223565,6 +224122,80 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -224991,6 +225622,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -225546,6 +226185,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -225704,7 +226363,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -231324,6 +232007,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -236154,6 +236861,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -236270,6 +236981,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -237138,6 +237853,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -249499,6 +250218,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -255381,6 +256105,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -255641,6 +256370,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -259378,6 +260114,15 @@ msgstr[3] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -262345,14 +263090,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -264970,6 +265707,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "" @@ -266042,6 +266787,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -266116,7 +266871,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -266124,7 +266879,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -266132,7 +266887,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -266140,7 +266895,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -266148,7 +266903,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -266156,7 +266911,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -266164,7 +266919,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -266172,7 +266927,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -273761,6 +274516,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/uk_UA.po b/lang/po/uk_UA.po index b3264229a641..84f5c31f8d58 100644 --- a/lang/po/uk_UA.po +++ b/lang/po/uk_UA.po @@ -5,7 +5,7 @@ msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Coolthulhu , 2023\n" "Language-Team: Ukrainian (Ukraine) (https://app.transifex.com/bn-team/teams/113585/uk_UA/)\n" "MIME-Version: 1.0\n" @@ -1492,10 +1492,18 @@ msgstr "" msgid "[Combat] One Down, Billions to Go…" msgstr "" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "" @@ -3904,10 +3912,26 @@ msgstr "" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "" + #: data/json/body_parts.json msgid "appendix" msgstr "" @@ -8048,6 +8072,17 @@ msgstr "" msgid "You're winded." msgstr "" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "" @@ -21981,34 +22016,106 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "" @@ -22017,30 +22124,93 @@ msgstr "" msgid "plop." msgstr "" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "" @@ -22049,6 +22219,16 @@ msgstr "" msgid "rustle." msgstr "" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "зомбі" +msgstr[1] "зомбі" +msgstr[2] "зомбі" +msgstr[3] "зомбі" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "" @@ -22057,6 +22237,15 @@ msgstr "" msgid "shuffling." msgstr "" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "" @@ -22065,18 +22254,61 @@ msgstr "" msgid "mechanical whirring." msgstr "" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -49490,8 +49722,8 @@ msgstr[3] "" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49505,8 +49737,8 @@ msgstr[3] "" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -49521,8 +49753,8 @@ msgstr[3] "" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." msgstr "" #: data/json/items/ammo/20x66mm.json @@ -51238,20 +51470,65 @@ msgid "" msgstr "" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm JHP, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." msgstr "" +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "" + #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json msgid "" @@ -51636,53 +51913,53 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "Одноступінчатий фугасний реактивний 93мм постріл для РПГ-7" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" msgstr[0] "" msgstr[1] "" msgstr[2] "" msgstr[3] "" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -76950,6 +77227,58 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -78190,6 +78519,7 @@ msgstr "" #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "" @@ -80993,6 +81323,7 @@ msgstr "" #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "жувальна гумка" @@ -88334,6 +88665,7 @@ msgstr "" #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "" @@ -122454,14 +122786,6 @@ msgid "" "of infesting sewer lines." msgstr "" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -123189,14 +123513,6 @@ msgid "" "envelope of scar tissue." msgstr "" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "зомбі" -msgstr[1] "зомбі" -msgstr[2] "зомбі" -msgstr[3] "зомбі" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -133522,7 +133838,8 @@ msgid "I'll kill you if you don't." msgstr "" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "" @@ -141338,10 +141655,6 @@ msgstr "" msgid "demon" msgstr "" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "" @@ -154682,6 +154995,16 @@ msgid "" "coming no further. Go away." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "" @@ -154718,6 +155041,20 @@ msgstr "" msgid "Alright, I'm leaving." msgstr "" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "" @@ -185591,6 +185928,15 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "" @@ -196008,6 +196354,15 @@ msgstr "" msgid "DinoLab Operating Theater Access Control" msgstr "" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "" @@ -209578,6 +209933,11 @@ msgstr "" msgid "RUNES" msgstr "" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "" @@ -209705,6 +210065,30 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "" @@ -213802,6 +214186,22 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -214075,6 +214475,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "" @@ -214083,6 +214484,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "" @@ -214155,6 +214557,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "" @@ -214163,6 +214566,7 @@ msgstr[2] "" msgstr[3] "" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "" @@ -214394,6 +214798,22 @@ msgstr[1] "" msgstr[2] "" msgstr[3] "" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -215400,6 +215820,102 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -216656,6 +217172,22 @@ msgid "" "protective equipment inside." msgstr "" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -217983,6 +218515,14 @@ msgid "" "much more expensive." msgstr "" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -218000,14 +218540,6 @@ msgid "" "with venom." msgstr "" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -221102,10 +221634,26 @@ msgid "" "human candy! Are you a real monster? Will you be able to devour it all?\"" msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "" @@ -223543,6 +224091,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "" @@ -223565,6 +224122,80 @@ msgid "" "retrodays tileset." msgstr "" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" +msgstr[1] "" +msgstr[2] "" +msgstr[3] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "" @@ -224991,6 +225622,14 @@ msgstr "" msgid "Debug Menu" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "" @@ -225546,6 +226185,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -225704,7 +226363,31 @@ msgstr "" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -231332,6 +232015,30 @@ msgstr "" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -236162,6 +236869,10 @@ msgstr "" msgid "Change [b]attery charge" msgstr "" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "" @@ -236278,6 +236989,10 @@ msgstr "" msgid "Player…" msgstr "" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -237146,6 +237861,10 @@ msgstr "" msgid "By how much? (in kJ, negative to discharge)" msgstr "" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -249507,6 +250226,11 @@ msgstr "" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "" @@ -255389,6 +256113,11 @@ msgstr "" msgid "Create World" msgstr "" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "" @@ -255649,6 +256378,13 @@ msgstr "" msgid "Sorry, something went wrong." msgstr "" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -259386,6 +260122,15 @@ msgstr[3] "" msgid "Mod version" msgstr "" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "" @@ -262353,14 +263098,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "" -msgstr[1] "" -msgstr[2] "" -msgstr[3] "" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -264978,6 +265715,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "" + #: src/options.cpp msgid "General" msgstr "" @@ -266050,6 +266795,16 @@ msgstr "" msgid "The amount of time to pause between animation frames in ms." msgstr "" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "" @@ -266124,7 +266879,7 @@ msgid "Font height" msgstr "" #: src/options.cpp -msgid "Set the font height. Requires restart." +msgid "Set the font height. Requires restart." msgstr "" #: src/options.cpp @@ -266132,7 +266887,7 @@ msgid "Font size" msgstr "" #: src/options.cpp -msgid "Set the font size. Requires restart." +msgid "Set the font size. Requires restart." msgstr "" #: src/options.cpp @@ -266140,7 +266895,7 @@ msgid "Map font width" msgstr "" #: src/options.cpp -msgid "Set the map font width. Requires restart." +msgid "Set the map font width. Requires restart." msgstr "" #: src/options.cpp @@ -266148,7 +266903,7 @@ msgid "Map font height" msgstr "" #: src/options.cpp -msgid "Set the map font height. Requires restart." +msgid "Set the map font height. Requires restart." msgstr "" #: src/options.cpp @@ -266156,7 +266911,7 @@ msgid "Map font size" msgstr "" #: src/options.cpp -msgid "Set the map font size. Requires restart." +msgid "Set the map font size. Requires restart." msgstr "" #: src/options.cpp @@ -266164,7 +266919,7 @@ msgid "Overmap font width" msgstr "" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." +msgid "Set the overmap font width. Requires restart." msgstr "" #: src/options.cpp @@ -266172,7 +266927,7 @@ msgid "Overmap font height" msgstr "" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." +msgid "Set the overmap font height. Requires restart." msgstr "" #: src/options.cpp @@ -266180,7 +266935,7 @@ msgid "Overmap font size" msgstr "" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." +msgid "Set the overmap font size. Requires restart." msgstr "" #: src/options.cpp @@ -273769,6 +274524,11 @@ msgstr "" msgid " [%s]" msgstr "" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "" + #: src/worldfactory.cpp msgid "N/A" msgstr "" diff --git a/lang/po/zh_CN.po b/lang/po/zh_CN.po index cce6bb3ac762..2fffa783df72 100644 --- a/lang/po/zh_CN.po +++ b/lang/po/zh_CN.po @@ -1,18 +1,18 @@ # # Translators: -# Caixukun , 2022 -# 皮皮山上的咕咕⑨, 2022 -# chenzhiyuan42, 2022 -# LuXts, 2022 +# WhiteCloud0123, 2023 +# LuXts, 2023 +# chenzhiyuan42, 2023 +# Caixukun , 2023 # 摸鱼哥, 2023 +# 皮皮山上的咕咕⑨, 2023 # Coolthulhu , 2023 -# WhiteCloud0123, 2023 # Jeremy Wu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Jeremy Wu , 2023\n" "Language-Team: Chinese (China) (https://app.transifex.com/bn-team/teams/113585/zh_CN/)\n" "MIME-Version: 1.0\n" @@ -1665,16 +1665,24 @@ msgid "" "A: Check the wiki, or ask the helpful people on the forum or at the chat channels. Links are provided in MOTD in the main menu." msgstr "" "问:我还有些问题这里没有找到答案,我该去问谁呢?\n" -"答:你可以查游戏百科cddawiki.chezzo.com/cdda_wiki,或者把你的问题发到smf.cataclysmdda.com的论坛或者freenode的#CataclysmDDA频道,我们将尽量回答。另外,既然你丫玩的是中文版,去百度cataclysmdda吧或者三大妈的cdda专区都会有筒子帮你的。by 五毛钱" +"答:查看wiki百科,或者在论坛或聊天频道询问热心的朋友。主菜单中的 MOTD 提供了相关链接。" #: data/json/achievements.json msgid "[Combat] One Down, Billions to Go…" msgstr "[战斗] 干掉一个,还有十亿个……" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "[战斗] 送葬者" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "[战斗] 猛然觉醒" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "[战斗] 和平主义者" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "[战斗] 十名死者" @@ -4051,10 +4059,23 @@ msgstr "永久发电机" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "安装在你体内的是一台由非太阳能供电的永久发电机。激活后,它的发电量加倍。如果你看到了这这个,你最好是处在调试模式。" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "测试用燃料电池CBM" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "太阳之力,在我掌中!安装在你体内的是一台由非太阳能供电的永久发电机。激活后,它的发电量加倍。如果你看到了这这个,你最好是处在调试模式。" + #: data/json/body_parts.json msgid "appendix" msgstr "附肢" @@ -8199,6 +8220,17 @@ msgstr "哮喘发作!你无法呼吸……" msgid "You're winded." msgstr "你被缠绕住了。" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "支气管痉挛" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "空气中的某些物质使呼吸变得更加困难,加重了你的哮喘症状。这会增加患哮喘发作的风险。" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "天花板掉落下来并砸在了你身上!" @@ -10321,7 +10353,7 @@ msgstr "添加为枪械模组" #: data/json/item_actions.json msgid "Repair/mend a gun" -msgstr "修理/维修枪械" +msgstr "修理/保养枪械" #: data/json/item_actions.json msgid "Repair a gun" @@ -22466,34 +22498,82 @@ msgid "seeing this is a bug" msgid_plural "seeing this is a bug" msgstr[0] "看见这个说明出bug了。" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "哺乳动物" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "哺乳动物" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "两栖动物" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "两栖动物" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "鸟类" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "鸟类" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "爬行动物" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "爬行动物" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "鱼类" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "鱼类" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "变种人" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "变种人" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "异界生物" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "异界生物" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "变形怪" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "变形怪" @@ -22502,30 +22582,72 @@ msgstr "变形怪" msgid "plop." msgstr "扑通声。" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "真菌" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "异界真菌" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "吸血植物" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "吸血植物" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "昆虫" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "昆虫" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "蜘蛛" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "蜘蛛" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "植物" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "植物" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "软体动物" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "软体动物" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "蠕虫" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "蠕虫" @@ -22534,6 +22656,13 @@ msgstr "蠕虫" msgid "rustle." msgstr "地下摩擦声。" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "丧尸" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "丧尸" @@ -22542,6 +22671,12 @@ msgstr "丧尸" msgid "shuffling." msgstr "蹒跚蹭地声。" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "机器人" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "机器人" @@ -22550,18 +22685,46 @@ msgstr "机器人" msgid "mechanical whirring." msgstr "机械嗡嗡声。" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "恐怖怪物" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "恐怖怪物" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "畸变体" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "异形" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "幻觉" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "人类" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "人类" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "未知物种" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -27272,7 +27435,7 @@ msgstr "气动武器" #. ~ weapon category name #: data/json/weapon_categories.json msgid "Elastic" -msgstr "橡皮筋" +msgstr "弹性" #: data/json/weather_type.json msgid "NULL Weather - BUG" @@ -37840,7 +38003,7 @@ msgstr ".45-70 弹" #: data/json/items/ammo_types.json msgid "nails" -msgstr "钉子" +msgstr "鐵釘" #: data/json/items/ammo_types.json msgid "barb" @@ -37848,7 +38011,7 @@ msgstr "毒刺" #: data/json/items/ammo_types.json msgid "BBs" -msgstr "BB弹" +msgstr "BB彈" #: data/json/items/ammo_types.json msgid "bolts" @@ -37864,7 +38027,7 @@ msgstr "小石子" #: data/json/items/ammo_types.json msgid "rocks" -msgstr "石头" +msgstr "石頭" #: data/json/items/ammo_types.json msgid "shot" @@ -38049,7 +38212,7 @@ msgstr "电池" #: data/json/items/ammo_types.json msgid "cents" -msgstr "美分" +msgstr "分" #: data/json/items/ammo_types.json msgid "plutonium" @@ -47506,9 +47669,9 @@ msgstr[0] "26X66mm 镖型弹(自制)" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "手工制造的盗版Rivtech的26x66mm 镖形弹,由于是无壳弹,所以不可拆解和复装。" +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "手工制造的Rivtech的20x66mm 镖形弹,由于是无壳弹,所以不可拆解和复装。" #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" @@ -47518,9 +47681,9 @@ msgstr[0] "26X66mm 猎鹿弹(自制)" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "手工制造的盗版Rivtech的26x66mm 猎鹿弹,由于是无壳弹,所以不可拆解和复装。" +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "手工制造的Rivtech的20x66mm 猎鹿弹,由于是无壳弹,所以不可拆解和复装。" #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -47531,9 +47694,9 @@ msgstr[0] "26X66mm 独头弹(自制)" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "手工制造的盗版Rivtech的26x66mm 合金弹,由于是无壳弹,所以不可拆解和复装。" +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." +msgstr "手工制造的Rivtech的20x66mm 合金弹,由于是无壳弹,所以不可拆解和复装。" #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" @@ -48951,16 +49114,52 @@ msgid "" msgstr "一枚用于卡尔古斯塔夫 M3 无后坐力炮的 84x246mm 烟雾弹,常用于发信号、指示目标和掩护部队。" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" msgstr[0] "8x40mm 空尖无壳弹(自制)" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#. ~ Description for {'str': '8x40mm JHP, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "手工制造的仿制8x40mm 空尖无壳弹。由于是无壳弹,因此不能被拆解或是复装。" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "8x40mm 无壳弹(自制)" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." -msgstr "小作坊制造的仿制8x40mm 无壳弹。由于是无壳弹,因此不能被拆解或是复装。" +msgstr "手工制造的仿制8x40mm 无壳弹。由于是无壳弹,因此不能被拆解或是复装。" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "8x40mm 高速穿甲无壳弹(自制)" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "手工制造的仿制8x40mm 高速穿甲无壳弹。由于是无壳弹,因此不能被拆解或是复装。" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "8x40mm 曳光无壳弹(自制)" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "手工制造的仿制8x40mm 曳光无壳弹。由于是无壳弹,因此不能被拆解或是复装。" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -49283,41 +49482,41 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "一管彩弹游戏里使用的非致命性小彩弹,几乎不能造成任何伤害。" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" -msgstr[0] "PG-7VL 93mm 火箭弹" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" +msgstr[0] "PG-7VL RPG-7 火箭弹" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "一枚用于RPG-7的93mm 单级高爆火箭弹。" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" -msgstr[0] "PG-7VR 64mm/105mm 火箭弹" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" +msgstr[0] "PG-7VR RPG-7 火箭弹" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "一枚用于RPG-7的64mm/105mm多级高爆火箭弹。" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" -msgstr[0] "TBG-7V 105mm 火箭弹" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" +msgstr[0] "TBG-7V RPG-7 火箭弹" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "一枚用于RPG-7的热压火箭弹。" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" -msgstr[0] "OG-7V 40mm 火箭弹" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" +msgstr[0] "OG-7V RPG-7 火箭弹" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -66900,7 +67099,7 @@ msgstr[0] "能量手枪" #: data/json/items/classes/gun.json msgid "elastic pistol" msgid_plural "elastic pistols" -msgstr[0] "橡皮筋手枪" +msgstr[0] "弹性手枪" #: data/json/items/classes/gun.json msgid "base rifle" @@ -66945,7 +67144,7 @@ msgstr[0] "电磁步枪" #: data/json/items/classes/gun.json msgid "elastic rifle" msgid_plural "elastic rifles" -msgstr[0] "橡皮筋步枪" +msgstr[0] "弹性步枪" #: data/json/items/classes/gun.json msgid "pneumatic rifle" @@ -70067,6 +70266,46 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "一个腌咸蛋。蛋白咸得齁人,但蛋黄美味可口而且保质期很长。" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "蒜叶婆罗门参欧姆蛋" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "一个蒜叶婆罗门参欧姆蛋。" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "野菜欧姆蛋" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "一个用野菜制作的欧姆蛋。" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "蘑菇欧姆蛋" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "一个用蘑菇制作的欧姆蛋。" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "西班牙欧姆蛋" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "一个西班牙欧姆蛋。" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" @@ -71070,6 +71309,7 @@ msgstr "又干又甜,吃多了会口渴。配上些巧克力和棉花糖会更 #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" msgstr[0] "曲奇饼" @@ -73288,6 +73528,7 @@ msgstr "无菌的生理盐水滴眼液,可以用来治疗眼部干燥,也可 #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "口香糖" @@ -79162,6 +79403,7 @@ msgstr "嘎嘣脆的美味华夫饼浇上枫糖浆,配上水果使它更甜、 #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" msgstr[0] "薄脆饼干" @@ -80301,7 +80543,7 @@ msgstr "一个通过加热线圈及推动空气使你的头发变干的电动工 #: data/json/items/generic/bathroom_house.json msgid "curling iron" msgid_plural "curling irons" -msgstr[0] " 卷发钳" +msgstr[0] "卷发钳" #. ~ Description for {'str': 'curling iron'} #: data/json/items/generic/bathroom_house.json @@ -107673,11 +107915,6 @@ msgid "" "of infesting sewer lines." msgstr "这是一种具有攻击性的变异盲蛇,地下的生活赋予了其淡黄色的躯体。这种生物在地下生活,并以其群聚在下水道的习性而命名。" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "变形怪" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -108284,11 +108521,6 @@ msgid "" "envelope of scar tissue." msgstr "一个畸形丧尸,它的皮肤变成了一层厚厚的、带硬壳的疤痕组织。" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "丧尸" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -118483,7 +118715,8 @@ msgid "I'll kill you if you don't." msgstr "要是不答应我就杀了你。" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "算了。" @@ -126411,10 +126644,6 @@ msgstr "怪物" msgid "demon" msgstr "恶魔" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "恐怖怪物" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "难以形容的野兽" @@ -140224,6 +140453,16 @@ msgid "" "coming no further. Go away." msgstr "站住。我不管你是怎么进来的,但你不能再往前走了。快离开。" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "我是被避难中心的商贩派来的。他们告诉我要把这个硬盘送给您。" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "商贩还提到您正在寻找帮助。" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "等等!什么??" @@ -140260,6 +140499,20 @@ msgstr "所以,关于那套防护装备?" msgid "Alright, I'm leaving." msgstr "好吧,我得走了。" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "明白了。请将硬盘放在对讲机下嵌入的盒子里。之后您可以离开。" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "[按对讲机的指示行事]" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "现在没有带硬盘,我会带着它回来。" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "不,现在离开。" @@ -166125,7 +166378,7 @@ msgstr "一套安装在旋转轴上的小型车轮,和办公室里的旋转椅 #: data/json/vehicleparts/wheel.json msgid "wheels" -msgstr "车轮" +msgstr "輪胎" #. ~ Description for {'str': 'wheels'} #: data/json/vehicleparts/wheel.json @@ -170298,6 +170551,12 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "一台经过改装的眼球无人机,用来当作浮空移动的加热器使用。它持续不断地朝四周释放暖气来加热封闭空间。" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "基因擢升人" @@ -180088,6 +180347,12 @@ msgstr "一套厚厚的皮甲,关键部位有精心放置的青铜甲,专门 msgid "DinoLab Operating Theater Access Control" msgstr "恐龙实验室手术中心控制台" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "恐龙" @@ -184858,7 +185123,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Haplosmashosaurus" msgid_plural "Haplosmashosaurus" -msgstr[0] "" +msgstr[0] "恐怖简棘龙" #. ~ Description for {'str_sp': 'Haplosmashosaurus'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184996,7 +185261,7 @@ msgstr "一具巨大的、蹒跚而行的四足恐龙尸体,背上有高耸的 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Spiked Gauntlet" msgid_plural "Spiked Gauntlets" -msgstr[0] "" +msgstr[0] "恐怖加斯顿龙" #. ~ Description for {'str': 'Spiked Gauntlet'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185009,7 +185274,7 @@ msgstr "一只全身布满肿胀肌肉和溃烂伤口、装备有厚重盔甲、 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Grim Gargoyle" msgid_plural "Grim Gargoyles" -msgstr[0] "" +msgstr[0] "恐怖怪嘴龙" #. ~ Description for {'str': 'Grim Gargoyle'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185021,7 +185286,7 @@ msgstr "这具巨大的恐龙尸体装备着厚重盔甲,并有着喙和坚硬 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Horrorpelta" msgid_plural "Horrorpeltas" -msgstr[0] "" +msgstr[0] "恐怖蜥结龙" #. ~ Description for {'str': 'Horrorpelta'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185046,7 +185311,7 @@ msgstr "这具巨大的恐龙尸体看上去像是一种巨大的史前犰狳。 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Panoply of Pain" msgid_plural "Panoply of Pains" -msgstr[0] "" +msgstr[0] "恐怖胄甲龙" #. ~ Description for {'str': 'Panoply of Pain'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185111,7 +185376,7 @@ msgstr "这具厚重装甲的四足恐龙丧尸有一个喙和大量尖刺的骨 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Horned Horror" msgid_plural "Horned Horrors" -msgstr[0] "" +msgstr[0] "恐怖包头龙" #. ~ Description for {'str': 'Horned Horror'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185126,7 +185391,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Cutler Crusher" msgid_plural "Cutler Crushers" -msgstr[0] "" +msgstr[0] "恐怖厚甲龙" #. ~ Description for {'str': 'Cutler Crusher'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185139,7 +185404,7 @@ msgstr "这具重装甲的四足恐龙尸体背部有数根长刺,尾巴上长 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Sinewy Striker" msgid_plural "Sinewy Strikers" -msgstr[0] "" +msgstr[0] "恐怖腱龙" #. ~ Description for {'str': 'Sinewy Striker'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185152,7 +185417,7 @@ msgstr "这只拖着脚步的羽毛恐龙尸体拥有异常肿胀的腿部、庞 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Dry Destroyer" msgid_plural "Dry Destroyers" -msgstr[0] "" +msgstr[0] "恐怖橡树龙" #. ~ Description for {'str': 'Dry Destroyer'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185205,7 +185470,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Roman Wrecker" msgid_plural "Roman Wreckers" -msgstr[0] "" +msgstr[0] "恐怖格里芬龙" #. ~ Description for {'str': 'Roman Wrecker'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185218,7 +185483,7 @@ msgstr "一只巨大的有鳞恐龙,有一个无齿的喙嘴和大的鼻弓, #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Pro Punishment" msgid_plural "Pro Punishments" -msgstr[0] "" +msgstr[0] "恐怖原栉龙" #. ~ Description for {'str': 'Pro Punishment'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185231,7 +185496,7 @@ msgstr "一只巨大的有鳞恐龙,有蹄,短喙和高大的头冠,已经 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Spiked Smasher" msgid_plural "Spiked Smashers" -msgstr[0] "" +msgstr[0] "恐怖龙栉龙" #. ~ Description for {'str': 'Spiked Smasher'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185272,7 +185537,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Hatchet Horror" msgid_plural "Hatchet Horrors" -msgstr[0] "" +msgstr[0] "恐怖赖氏龙" #. ~ Description for {'str': 'Hatchet Horror'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185487,7 +185752,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Godlike Goliath" msgid_plural "Godlike Goliath" -msgstr[0] "" +msgstr[0] "“神”歌莱亚" #. ~ Description for {'str_sp': 'Godlike Goliath'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -191501,6 +191766,11 @@ msgstr "药水" msgid "RUNES" msgstr "符文" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "魔力聚焦" @@ -191634,6 +191904,21 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "魔法师度假地" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "魔法师秘密地下研究室" @@ -195365,6 +195650,16 @@ msgid "sledge hammer +2" msgid_plural "sledge hammer +2s" msgstr[0] "大钢锤 +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -195536,11 +195831,13 @@ msgid_plural "cavalry sabre +2s" msgstr[0] "骑兵刀 +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "撬棍 +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "撬棍 +2" @@ -195586,11 +195883,13 @@ msgid_plural "combat knife +2s" msgstr[0] "战术匕首 +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "猎刀 +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "猎刀 +2" @@ -195735,6 +196034,16 @@ msgid "dao +2" msgid_plural "dao +2s" msgstr[0] "中式刀 +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -196567,6 +196876,66 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "一大枚银币。当念出硬币背面的文字时,它会变成正面图案内的物品,比如说这枚上面的撬棍。" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -197555,6 +197924,19 @@ msgid "" "protective equipment inside." msgstr "一本皮革装订的书,封面上画着一个盾牌挡住了龙炎。里面描述了把各种怪物毛皮制成防护装备的方法。" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -198506,6 +198888,11 @@ msgid "" "much more expensive." msgstr "一个由山铜制成的车架。比钢制车架要坚固得多,但同时也比它昂贵得多。" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "恶魔蜘蛛" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -198521,11 +198908,6 @@ msgid "" msgstr "" "尽管它有小狗那么大,但你可以看出这是一只非常年轻的蜘蛛。红色的身体是你给它取这个名字的原因;在大灾变之前从没见过这种生物。它行动敏捷,巨大毒牙正滴下毒液。" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "恶魔蜘蛛" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -201300,10 +201682,20 @@ msgstr "" "一张介绍某种糖果的传单。上面画着一个用光滑的糖果做成的闪闪发光的人,正害怕地看着你。\"糖人,世上首个真人大小的糖果!你真是个怪物吗?你能把它吞下吗?\"" " " +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "唰啦。" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "啵。" @@ -203599,6 +203991,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "在乡间玩耍:只有农场、森林和村庄。建议城市大小设置为1,间距设置为8。" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "Lua SaveLoad 测试" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "用于测试Lua保存/加载API的模组。" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "发现玩家图标,HitButton_iso版" @@ -203621,6 +204022,77 @@ msgid "" "retrodays tileset." msgstr "如果某个生物发现了你,会显示一个!图标。专为 retrodays 贴图包设计。" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "敏捷速度加成" @@ -205047,6 +205519,14 @@ msgstr "切换调试信息" msgid "Debug Menu" msgstr "调试菜单" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "Lua 控制台" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "重新加载Lua代码" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "查看气味视图" @@ -205602,6 +206082,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -205760,7 +206260,31 @@ msgstr "设置炮塔瞄准模式" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -205914,6 +206438,8 @@ msgid "" "\n" "%d out of %d, working on %-20s" msgstr "" +"\n" +"%d个中的%d个,正在处理%-20s。" #: src/activity_actor.cpp msgid "You cause a short circuit!" @@ -205986,7 +206512,7 @@ msgstr "失败机会=%f%%" #: src/activity_handlers.cpp #, c-format msgid "You discover: %s!" -msgstr "" +msgstr "你发现了:%s!" #: src/activity_handlers.cpp #, c-format @@ -211328,6 +211854,30 @@ msgstr "abcdefghijklmnopqrstuvwxyz" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "唰哗轰嘭砰嘘飕哗铛咔嗒叮吱嗞啦噗哒嗒哗啦呼噜噼啪" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -216204,6 +216754,10 @@ msgstr "信息…" msgid "Change [b]attery charge" msgstr "修改载具电量" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "载具…" @@ -216320,6 +216874,10 @@ msgstr "退出至主菜单" msgid "Player…" msgstr "玩家…" +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "Lua 控制台" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -217192,6 +217750,10 @@ msgstr "那里没有载具。" msgid "By how much? (in kJ, negative to discharge)" msgstr "增加多少?(单位KJ,负数为减少)" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -222592,7 +223154,7 @@ msgstr "斩击" #: src/game_inventory.cpp msgid "BULLET" -msgstr "" +msgstr "子弹" #: src/game_inventory.cpp msgid "ACID" @@ -223081,7 +223643,7 @@ msgstr "你没有任何可供安装的生化插件。" #: src/game_inventory.cpp msgid "COMPLICATION CHANCE" -msgstr "" +msgstr "并发症几率" #: src/game_inventory.cpp msgid "OPERATION DURATION" @@ -227635,20 +228197,20 @@ msgstr "* 这份食物 会腐坏,在室温下保质期大 #: src/item.cpp msgid "" "* Current storage conditions do not protect this item from rot." -msgstr "* 当前储存条件 无法 保护该物品不腐烂." +msgstr "* 当前储存条件 无法 保护该物品不腐烂。" #: src/item.cpp #, c-format msgid "" "* Current storage conditions partially protect this item " "from rot. It will stay fresh at least %s." -msgstr "" +msgstr "* 当前储存条件 部分地 保护此物品免受腐烂。 它至少会保持新鲜 %s。" #: src/item.cpp msgid "" "* Current storage conditions fully protect this item from rot." " It will stay fresh indefinitely." -msgstr "" +msgstr "* 当前储存条件 完全 保护此物品免受腐烂。它将无限期保持新鲜。" #: src/item.cpp msgid "* It seems that deep freezing killed all parasites." @@ -227907,7 +228469,7 @@ msgstr "增加模组位置:" #: src/item.cpp msgid "Used on:" -msgstr "" +msgstr "使用在:" #: src/item.cpp msgid "" @@ -227920,6 +228482,8 @@ msgid "" "\n" " Category: " msgstr "" +"\n" +" 类别: " #: src/item.cpp msgid "Incompatible with mod location: " @@ -229794,7 +230358,7 @@ msgstr "这只 %s 不想要这种食物。" #: src/iuse.cpp #, c-format msgid "Tame which animal with the %s?" -msgstr "" +msgstr "用%s驯服哪种动物?" #: src/iuse.cpp msgid "Are you sure you want to feed a person the dog food?" @@ -229821,6 +230385,11 @@ msgstr "%s 一把将它从你手中拍落了!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "你想喂 %s 一些 %s,但它消失了!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "你想用狗粮喂它,但它咬了你的手指头!" @@ -232760,7 +233329,7 @@ msgstr "下次在食用应当热食的时候,你会尝试使用%s来加热食 #: src/iuse.cpp #, c-format msgid "You will no longer use %s to heat food." -msgstr "" +msgstr "你不会再用%s来加热食物。" #: src/iuse.cpp msgid "This electric grid has no connections." @@ -235699,6 +236268,11 @@ msgstr "" msgid "Create World" msgstr "创建世界" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "需要Lua!" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "漏洞?建议?通过MOTD中的链接来报告它们。" @@ -235959,6 +236533,13 @@ msgstr "确定要删除 %s 吗?" msgid "Sorry, something went wrong." msgstr "抱歉,出错了!" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "%s 需要支持Lua的游戏版本!" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -236104,7 +236685,7 @@ msgstr " 被坠落的残骸击中!" #: src/map.cpp #, c-format msgid "The shot is stopped by the %s!" -msgstr "" +msgstr "这一击被%s挡住了!" #: src/map.cpp msgid "laser beam" @@ -239793,6 +240374,15 @@ msgstr[0] "" msgid "Mod version" msgstr "Mod 版本" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "需要Lua" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "modinfo文件路径" @@ -242754,11 +243344,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "专注值平衡点:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "人类" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -245394,6 +245979,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "与 SDL、图块、图集和声音有关的信息。" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "来自Lua脚本的讯息。" + #: src/options.cpp msgid "General" msgstr "常规" @@ -246475,6 +247068,16 @@ msgstr "动画延时" msgid "The amount of time to pause between animation frames in ms." msgstr "每帧动画之间的延迟时间。以毫秒为单位。" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "闪烁效果速度" @@ -246542,71 +247145,71 @@ msgstr "字体宽度" #: src/options.cpp msgid "Set the font width. Requires restart." -msgstr "" +msgstr "设置字体宽度,需要重新启动。" #: src/options.cpp msgid "Font height" msgstr "字体高度" #: src/options.cpp -msgid "Set the font height. Requires restart." -msgstr "" +msgid "Set the font height. Requires restart." +msgstr "设置字体高度,需要重新启动。" #: src/options.cpp msgid "Font size" msgstr "字体大小" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "" +msgid "Set the font size. Requires restart." +msgstr "设置字体大小,需要重新启动。" #: src/options.cpp msgid "Map font width" msgstr "地图字体宽度" #: src/options.cpp -msgid "Set the map font width. Requires restart." -msgstr "" +msgid "Set the map font width. Requires restart." +msgstr "设置地图字体宽度,需要重新启动。" #: src/options.cpp msgid "Map font height" msgstr "地图字体高度" #: src/options.cpp -msgid "Set the map font height. Requires restart." -msgstr "" +msgid "Set the map font height. Requires restart." +msgstr "设置地图字体高度,需要重新启动。" #: src/options.cpp msgid "Map font size" msgstr "地图字体大小" #: src/options.cpp -msgid "Set the map font size. Requires restart." -msgstr "" +msgid "Set the map font size. Requires restart." +msgstr "设置地图字体大小,需要重新启动。" #: src/options.cpp msgid "Overmap font width" msgstr "大地图字体宽度" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." -msgstr "" +msgid "Set the overmap font width. Requires restart." +msgstr "设置大地图字体宽度,需要重新启动。" #: src/options.cpp msgid "Overmap font height" msgstr "大地图字体高度" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." -msgstr "" +msgid "Set the overmap font height. Requires restart." +msgstr "设置大地图字体高度,需要重新启动。" #: src/options.cpp msgid "Overmap font size" msgstr "大地图字体大小" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." -msgstr "" +msgid "Set the overmap font size. Requires restart." +msgstr "设置大地图字体大小,需要重新启动。" #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -254189,6 +254792,11 @@ msgstr "缺失模组" msgid " [%s]" msgstr " [%s]" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "(需要Lua) " + #: src/worldfactory.cpp msgid "N/A" msgstr "无" diff --git a/lang/po/zh_TW.po b/lang/po/zh_TW.po index 50928b35cdc1..16296a186c31 100644 --- a/lang/po/zh_TW.po +++ b/lang/po/zh_TW.po @@ -1,18 +1,18 @@ # # Translators: -# 皮皮山上的咕咕⑨, 2022 -# Caixukun , 2022 -# chenzhiyuan42, 2022 -# LuXts, 2022 -# 摸鱼哥, 2023 +# LuXts, 2023 # Collapas Alton, 2023 +# chenzhiyuan42, 2023 +# Caixukun , 2023 +# 摸鱼哥, 2023 +# 皮皮山上的咕咕⑨, 2023 # Coolthulhu , 2023 # Jeremy Wu , 2023 # msgid "" msgstr "" "Project-Id-Version: cataclysm-bn\n" -"POT-Creation-Date: 2023-08-03 04:45+0000\n" +"POT-Creation-Date: 2023-09-02 01:37+0000\n" "Last-Translator: Jeremy Wu , 2023\n" "Language-Team: Chinese (Taiwan) (https://app.transifex.com/bn-team/teams/113585/zh_TW/)\n" "MIME-Version: 1.0\n" @@ -1667,16 +1667,24 @@ msgid "" "A: Check the wiki, or ask the helpful people on the forum or at the chat channels. Links are provided in MOTD in the main menu." msgstr "" "问:我还有些问题这里没有找到答案,我该去问谁呢?\n" -"答:你可以查游戏百科cddawiki.chezzo.com/cdda_wiki,或者把你的问题发到smf.cataclysmdda.com的论坛或者freenode的#CataclysmDDA频道,我们将尽量回答。另外,既然你丫玩的是中文版,去百度cataclysmdda吧或者三大妈的cdda专区都会有筒子帮你的。by 五毛钱" +"答:查看wiki百科,或者在论坛或聊天频道询问热心的朋友。主菜单中的 MOTD 提供了相关链接。" #: data/json/achievements.json msgid "[Combat] One Down, Billions to Go…" msgstr "[战斗] 干掉一个,还有十亿个……" +#: data/json/achievements.json +msgid "[Combat] The Undertaker" +msgstr "[战斗] 送葬者" + #: data/json/achievements.json msgid "[Combat] Rude Awakening" msgstr "[战斗] 猛然觉醒" +#: data/json/achievements.json +msgid "[Combat] Pacifist" +msgstr "[战斗] 和平主义者" + #: data/json/achievements.json msgid "[Combat] Decamate" msgstr "[战斗] 十名死者" @@ -2033,7 +2041,7 @@ msgstr "非常低廉的价格,提供非凡的小工具!" #: data/json/achievements.json msgid "[Skill] Robber Baron" -msgstr "[Skill] Robber Baron" +msgstr "[技能] 强盗大亨" #. ~ Description for {'str': '[Skill] Robber Baron'} #: data/json/achievements.json @@ -2551,7 +2559,7 @@ msgstr "一個動態偵測警報系統能夠偵測 5 呎遠的範圍並通知你 #: data/json/bionics.json data/json/items/bionics.json msgid "Squeaky Ankles" msgid_plural "Squeaky Ankles" -msgstr[0] "" +msgstr[0] "腳踝重響" #. ~ Description for {'str': 'Squeaky Ankles'} #: data/json/bionics.json @@ -3635,7 +3643,7 @@ msgstr "你的神經系統透過生化刺激裝置增強, 讓你獲得額外 10% #: data/json/bionics.json data/json/items/bionics.json msgid "Wire-Induced Stiffness" msgid_plural "Wire-Induced Stiffnesses" -msgstr[0] "" +msgstr[0] "感電僵硬" #. ~ Description for {'str': 'Wire-Induced Stiffness'} #: data/json/bionics.json @@ -3706,7 +3714,7 @@ msgstr "這個實驗性的插件能夠把空間折疊, 消耗大量的能量, #: data/json/bionics.json data/json/items/bionics.json msgid "Self-Locking Thumbs" msgid_plural "Self-Locking Thumbs" -msgstr[0] "" +msgstr[0] "拇指自鎖" #. ~ Description for {'str': 'Self-Locking Thumbs'} #: data/json/bionics.json @@ -4046,10 +4054,23 @@ msgstr "永久发电机" #: data/json/bionics.json data/json/items/bionics.json msgid "" "Installed within you is a perpetual generator powered by nonsensoleum. When" -" activated it's power gen doubles. If you are seeing this, you'd better be " +" activated its power gen doubles. If you are seeing this, you'd better be " "debugging." msgstr "安装在你体内的是一台由非太阳能供电的永久发电机。激活后,它的发电量加倍。如果你看到了这这个,你最好是处在调试模式。" +#: data/json/bionics.json data/json/items/bionics.json +msgid "Debug Fuel Cell CBM" +msgid_plural "Debug Fuel Cell CBMs" +msgstr[0] "测试用燃料电池CBM" + +#. ~ Description for {'str': 'Debug Fuel Cell CBM'} +#: data/json/bionics.json data/json/items/bionics.json +msgid "" +"The power of the sun, in the palm of my hand! Installed within you is a " +"perpetual generator powered by nonsensoleum. When activated its power gen " +"doubles. If you are seeing this, you'd better be debugging." +msgstr "太阳之力,在我掌中!安装在你体内的是一台由非太阳能供电的永久发电机。激活后,它的发电量加倍。如果你看到了这这个,你最好是处在调试模式。" + #: data/json/body_parts.json msgid "appendix" msgstr "附錄" @@ -8195,6 +8216,17 @@ msgstr "哮喘发作!你无法呼吸……" msgid "You're winded." msgstr "你覺得喘不過氣。" +#: data/json/effects.json +msgid "Bronchospasms" +msgstr "支气管痉挛" + +#. ~ Description of effect 'Bronchospasms'. +#: data/json/effects.json +msgid "" +"Something in the air is making it harder to breathe, aggravating your " +"asthma. Increases the chance of suffering an asthma attack." +msgstr "空气中的某些物质使呼吸变得更加困难,加重了你的哮喘症状。这会增加患哮喘发作的风险。" + #: data/json/effects.json msgid "The ceiling collapses on you!" msgstr "天花板砸到你了!" @@ -10317,7 +10349,7 @@ msgstr "附掛槍械模組" #: data/json/item_actions.json msgid "Repair/mend a gun" -msgstr "修理枪械" +msgstr "修理/保養槍械" #: data/json/item_actions.json msgid "Repair a gun" @@ -12367,7 +12399,7 @@ msgstr "" #: data/mods/Magiclysm/martialarts.json msgid "Fior Di Battaglia" msgid_plural "Fior Di Battaglia" -msgstr[0] "" +msgstr[0] "戰鬥之花" #. ~ Description for martial art '{'str': 'Fior Di Battaglia'}' #: data/json/martialarts.json @@ -14791,7 +14823,7 @@ msgstr "%1$s试图刺击,但是没能穿透护甲!" #: data/json/monster_attacks.json msgid "acid dart volley" msgid_plural "acid dart volleys" -msgstr[0] "" +msgstr[0] "酸性飛鏢" #: data/json/monster_attacks.json data/json/items/fake.json msgid "Fake gun that fires acid globs." @@ -14837,7 +14869,7 @@ msgstr "步槍" #: data/json/monster_attacks.json msgid "acid dart gun" msgid_plural "acid dart guns" -msgstr[0] "" +msgstr[0] "酸性飛鏢槍" #: data/json/morale_types.json msgid "Enjoyed %s" @@ -15258,7 +15290,7 @@ msgstr "這個炸藥的引線已經點燃並嘶嘶作響。將會隨時被引爆 #: data/json/not_really_obsolete.json msgid "fragment bomb" msgid_plural "fragment bombs" -msgstr[0] "" +msgstr[0] "破片炸彈" #. ~ Use action msg for {'str': 'fragment bomb'}. #. ~ Use action msg for {'str': 'nail bomb'}. @@ -15331,7 +15363,7 @@ msgstr "核融合電池" #: data/json/not_really_obsolete.json msgid "fusion pack" msgid_plural "fusion packs" -msgstr[0] "" +msgstr[0] "核融合能源包" #. ~ Description for {'str': 'fusion pack'} #: data/json/not_really_obsolete.json @@ -15345,7 +15377,7 @@ msgstr "" #: data/json/not_really_obsolete.json msgid "bootleg fusion pack" msgid_plural "bootleg fusion packs" -msgstr[0] "" +msgstr[0] "自製核融合能源包" #. ~ Description for {'str': 'bootleg fusion pack'} #: data/json/not_really_obsolete.json @@ -15559,7 +15591,7 @@ msgstr "這是一個自製的爆炸裝置, 由一個裝滿黑火藥和廢金屬 #: data/json/not_really_obsolete.json msgid "frame loom" msgid_plural "frame looms" -msgstr[0] "" +msgstr[0] "織布架" #. ~ Description for {'str': 'frame loom'} #: data/json/not_really_obsolete.json @@ -22486,34 +22518,82 @@ msgid "seeing this is a bug" msgid_plural "seeing this is a bug" msgstr[0] "見到這句話本身代表出現bug了" +#: data/json/species.json +msgid "mammal" +msgid_plural "mammals" +msgstr[0] "哺乳动物" + +#. ~ Description for {'str': 'mammal'} #: data/json/species.json msgid "a mammal" msgstr "哺乳动物" +#: data/json/species.json +msgid "amphibian" +msgid_plural "amphibians" +msgstr[0] "两栖动物" + +#. ~ Description for {'str': 'amphibian'} #: data/json/species.json msgid "an amphibian" msgstr "两栖动物" +#: data/json/species.json +msgid "bird" +msgid_plural "birds" +msgstr[0] "鸟类" + +#. ~ Description for {'str': 'bird'} #: data/json/species.json msgid "a bird" msgstr "鸟类" +#: data/json/species.json +msgid "reptile" +msgid_plural "reptiles" +msgstr[0] "爬行动物" + +#. ~ Description for {'str': 'reptile'} #: data/json/species.json msgid "a reptile" msgstr "爬行动物" +#: data/json/species.json +msgid "fish" +msgid_plural "fish" +msgstr[0] "鱼类" + +#. ~ Description for {'str_sp': 'fish'} #: data/json/species.json msgid "a fish" msgstr "鱼类" +#: data/json/species.json +msgid "mutant" +msgid_plural "mutants" +msgstr[0] "变种人" + +#. ~ Description for {'str': 'mutant'} #: data/json/species.json msgid "a mutant" msgstr "变种人" +#: data/json/species.json +msgid "nether creature" +msgid_plural "nether creatures" +msgstr[0] "异界生物" + +#. ~ Description for {'str': 'nether creature'} #: data/json/species.json msgid "a nether creature" msgstr "异界生物" +#: data/json/species.json data/json/monsters/slimes.json +msgid "blob" +msgid_plural "blobs" +msgstr[0] "黏球怪" + +#. ~ Description for {'str': 'blob'} #: data/json/species.json msgid "a blob" msgstr "变形怪" @@ -22522,30 +22602,72 @@ msgstr "变形怪" msgid "plop." msgstr "扑通声。" +#: data/json/species.json +msgid "fungus" +msgid_plural "fungi" +msgstr[0] "真菌" + +#. ~ Description for {'str': 'fungus', 'str_pl': 'fungi'} #: data/json/species.json msgid "a fungus" msgstr "真菌" +#: data/json/species.json +msgid "leech plant" +msgid_plural "leech plants" +msgstr[0] "吸血植物" + +#. ~ Description for {'str': 'leech plant'} #: data/json/species.json msgid "a leech plant" msgstr "吸血植物" +#: data/json/species.json +msgid "insect" +msgid_plural "insects" +msgstr[0] "昆虫" + +#. ~ Description for {'str': 'insect'} #: data/json/species.json msgid "an insect" msgstr "昆蟲" +#: data/json/species.json +msgid "spider" +msgid_plural "spiders" +msgstr[0] "蜘蛛" + +#. ~ Description for {'str': 'spider'} #: data/json/species.json msgid "a spider" msgstr "蜘蛛" +#: data/json/species.json +msgid "plant" +msgid_plural "plants" +msgstr[0] "植物" + +#. ~ Description for {'str': 'plant'} #: data/json/species.json msgid "a plant" msgstr "植物" +#: data/json/species.json +msgid "mollusk" +msgid_plural "mollusks" +msgstr[0] "软体动物" + +#. ~ Description for {'str': 'mollusk'} #: data/json/species.json msgid "a mollusk" msgstr "软体动物" +#: data/json/species.json +msgid "worm" +msgid_plural "worms" +msgstr[0] "蠕虫" + +#. ~ Description for {'str': 'worm'} #: data/json/species.json msgid "a worm" msgstr "蠕虫" @@ -22554,6 +22676,13 @@ msgstr "蠕虫" msgid "rustle." msgstr "地下摩擦声。" +#: data/json/species.json data/json/monsters/zed-classic.json +#: data/json/npcs/talk_tags.json +msgid "zombie" +msgid_plural "zombies" +msgstr[0] "殭屍" + +#. ~ Description for {'str': 'zombie'} #: data/json/species.json msgid "a zombie" msgstr "殭屍" @@ -22562,6 +22691,12 @@ msgstr "殭屍" msgid "shuffling." msgstr "蹒跚蹭地声。" +#: data/json/species.json +msgid "robot" +msgid_plural "robots" +msgstr[0] "机器人" + +#. ~ Description for {'str': 'robot'} #: data/json/species.json msgid "a robot" msgstr "机器人" @@ -22570,18 +22705,46 @@ msgstr "机器人" msgid "mechanical whirring." msgstr "机械嗡嗡声。" +#: data/json/species.json data/json/npcs/talk_tags.json +msgid "horror" +msgid_plural "horrors" +msgstr[0] "恐怖怪物" + +#. ~ Description for {'str': 'horror'} #: data/json/species.json msgid "a horror" msgstr "恐怖怪物" +#: data/json/species.json +msgid "abberation" +msgid_plural "abberations" +msgstr[0] "畸变体" + +#. ~ Description for {'str': 'abberation'} #: data/json/species.json msgid "an aberration" msgstr "畸形" +#: data/json/species.json +msgid "hallucination" +msgid_plural "hallucinations" +msgstr[0] "幻觉" + +#: data/json/species.json src/mtype.cpp +msgid "human" +msgid_plural "humans" +msgstr[0] "人類" + +#. ~ Description for {'str': 'human'} #: data/json/species.json msgid "a human" msgstr "人类" +#: data/json/species.json +msgid "unknown species" +msgid_plural "unknown species" +msgstr[0] "未知物种" + #: data/json/speech.json data/mods/Aftershock/speech.json #: data/mods/CrazyCataclysm/crazy_speech.json msgid "\"Hello?\"" @@ -26789,7 +26952,7 @@ msgstr "过滤" #: src/magic.cpp src/map_extras.cpp src/recipe.cpp msgid "none" msgid_plural "none" -msgstr[0] "" +msgstr[0] "無" #: data/json/traps.json data/json/items/tool/traps.json msgid "bubble wrap" @@ -27847,7 +28010,7 @@ msgstr "一个将建筑的电网连接到车辆的电源输出口。 使用时 #: data/json/items/fake.json msgid "grid welder" msgid_plural "grid welders" -msgstr[0] "" +msgstr[0] "焊槍(電網)" #. ~ Description for grid welder #: data/json/furniture_and_terrain/furniture-appliances.json @@ -28006,7 +28169,7 @@ msgstr "" #: data/json/items/fake.json msgid "grid electrolysis kit" msgid_plural "grid electrolysis kits" -msgstr[0] "" +msgstr[0] "電解工具箱(電網)" #. ~ Description for grid electrolysis kit #: data/json/furniture_and_terrain/furniture-appliances.json @@ -28922,7 +29085,7 @@ msgstr "中间有暗球的黄色花朵。有时被称为牛眼雏菊。" #: data/json/obsoletion/items.json msgid "lily" msgid_plural "lilies" -msgstr[0] "" +msgstr[0] "百合花" #. ~ Description for lily #: data/json/furniture_and_terrain/furniture-flora.json @@ -29232,7 +29395,7 @@ msgstr "一套用于安装和拆卸生化插件的医用手术设备。设定手 #: data/json/items/tool/med.json msgid "Autodoc operation couch" msgid_plural "Autodoc operation couchs" -msgstr[0] "" +msgstr[0] "全自動醫療儀手術台" #. ~ Description for Autodoc operation couch #: data/json/furniture_and_terrain/furniture-medical.json @@ -29490,7 +29653,7 @@ msgstr "別偷看!" #: data/json/items/fake.json msgid "centrifuge" msgid_plural "centrifuges" -msgstr[0] "" +msgstr[0] "離心機" #. ~ Description for centrifuge #: data/json/furniture_and_terrain/furniture-medical.json @@ -32974,7 +33137,7 @@ msgstr "柔軟的黃色地毯。" #: data/json/items/resources/home_improvement.json msgid "green carpet" msgid_plural "green carpets" -msgstr[0] "" +msgstr[0] "綠地毯" #. ~ Description for green carpet #: data/json/furniture_and_terrain/terrain-floors_indoor.json @@ -32985,7 +33148,7 @@ msgstr "柔軟的綠色地毯。" #: data/json/items/resources/home_improvement.json msgid "purple carpet" msgid_plural "purple carpets" -msgstr[0] "" +msgstr[0] "紫地毯" #. ~ Description for purple carpet #: data/json/furniture_and_terrain/terrain-floors_indoor.json @@ -35170,7 +35333,7 @@ msgstr "交通标志,用于指示水平铁路交叉口——如果火车还在 #: data/json/items/generic.json msgid "small railroad track" msgid_plural "small railroad tracks" -msgstr[0] "" +msgstr[0] "窄軌軌道" #. ~ Description for small railroad track #: data/json/furniture_and_terrain/terrain-railroads.json @@ -37154,7 +37317,7 @@ msgstr "一些自由浮動的電池料。 可以重填進可充式電池內。 #: data/json/items/ammo.json msgid "radioisotope thermoelectric generator" msgid_plural "radioisotope thermoelectric generators" -msgstr[0] "" +msgstr[0] "放射性熱能發電機" #. ~ Description for {'str': 'radioisotope thermoelectric generator'} #: data/json/items/ammo.json @@ -37173,7 +37336,7 @@ msgstr "" #: data/json/items/ammo.json msgid "aluminum foil" msgid_plural "aluminum foils" -msgstr[0] "" +msgstr[0] "鋁箔" #. ~ Description for {'str': 'aluminum foil'} #: data/json/items/ammo.json @@ -37185,7 +37348,7 @@ msgstr "鋁製的箔片, 以前用錫來製作, 所以也被稱為錫箔。" #: data/json/items/ammo.json msgid "cent" msgid_plural "cents" -msgstr[0] "" +msgstr[0] "美分" #. ~ Description for {'str': 'cent'} #. ~ Description for {'str': 'placeholder ammunition'} @@ -37207,7 +37370,7 @@ msgstr "一小段棉線, 能夠補充針線包。" #: data/json/items/ammo.json msgid "sinew" msgid_plural "sinews" -msgstr[0] "" +msgstr[0] "筋腱" #. ~ Description for {'str': 'sinew'} #: data/json/items/ammo.json @@ -37217,7 +37380,7 @@ msgstr "從屍體切割下的堅韌的筋, 可當做縫線。" #: data/json/items/ammo.json msgid "plant fiber" msgid_plural "plant fibers" -msgstr[0] "" +msgstr[0] "植物纖維" #. ~ Description for {'str': 'plant fiber'} #: data/json/items/ammo.json @@ -37237,7 +37400,7 @@ msgstr "毛紗能夠用來織成羊毛衣物。" #: data/json/items/ammo.json msgid "soap bar" msgid_plural "soap bars" -msgstr[0] "" +msgstr[0] "肥皂條" #. ~ Description for {'str': 'soap bar'} #: data/json/items/ammo.json @@ -37247,7 +37410,7 @@ msgstr "做成塊狀的肥皂。" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "duct tape" msgid_plural "duct tapes" -msgstr[0] "" +msgstr[0] "強力膠帶" #. ~ Description for {'str': 'duct tape'} #: data/json/items/ammo.json @@ -37257,7 +37420,7 @@ msgstr "一捆非常強韌的膠帶。用途很多。" #: data/json/items/ammo.json msgid "rolling paper" msgid_plural "rolling papers" -msgstr[0] "" +msgstr[0] "捲菸紙" #. ~ Description for {'str': 'rolling paper'} #: data/json/items/ammo.json @@ -37267,7 +37430,7 @@ msgstr "一張用來捲香煙的薄紙。" #: data/json/items/ammo.json msgid "copper wire" msgid_plural "copper wires" -msgstr[0] "" +msgstr[0] "銅線" #. ~ Description for {'str': 'copper wire'} #: data/json/items/ammo.json @@ -37277,7 +37440,7 @@ msgstr "包覆著塑膠外皮的銅纜線。一般用於小型電子產品。" #: data/json/items/ammo.json data/mods/Aftershock/items/item_overrides.json msgid "plutonium fuel cell" msgid_plural "plutonium fuel cells" -msgstr[0] "" +msgstr[0] "鈽燃料電池" #. ~ Description for {'str': 'plutonium fuel cell'} #: data/json/items/ammo.json @@ -37294,7 +37457,7 @@ msgstr "" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "plutonium slurry" msgid_plural "plutonium slurry" -msgstr[0] "" +msgstr[0] "鈽漿" #. ~ Description for {'str_sp': 'plutonium slurry'} #. ~ Description for {'str_sp': 'watery plutonium slurry'} @@ -37311,7 +37474,7 @@ msgstr[0] "稀釋鈽漿液" #: data/json/items/ammo.json data/json/snippets/music.json msgid "rock" msgid_plural "rocks" -msgstr[0] "" +msgstr[0] "石頭" #. ~ Description for {'str': 'rock'} #: data/json/items/ammo.json @@ -37323,7 +37486,7 @@ msgstr "棒球大小的石頭。可用來製作近戰武器, 也可以朝著敵 #: data/json/items/ammo.json msgid "pebble" msgid_plural "pebbles" -msgstr[0] "" +msgstr[0] "小石子" #. ~ Description for {'str': 'pebble'} #: data/json/items/ammo.json @@ -37333,7 +37496,7 @@ msgstr "一把鵝卵石, 可以用在投石帶或彈弓上。" #: data/json/items/ammo.json msgid "clay pellet" msgid_plural "clay pellets" -msgstr[0] "" +msgstr[0] "陶彈丸" #. ~ Description for {'str': 'clay pellet'} #: data/json/items/ammo.json @@ -37345,7 +37508,7 @@ msgstr "一把陶製的圓球, 可以用在投石帶或彈弓上。" #: data/json/items/ammo.json msgid "marble" msgid_plural "marbles" -msgstr[0] "" +msgstr[0] "玻璃彈珠" #. ~ Description for {'str': 'marble'} #: data/json/items/ammo.json @@ -37366,7 +37529,7 @@ msgstr "一盒滾珠軸承, 可以用在投石帶或彈弓上。" #: data/json/items/ammo.json msgid "BB" msgid_plural "BBs" -msgstr[0] "" +msgstr[0] "BB彈" #. ~ Description for {'str': 'BB'} #: data/json/items/ammo.json @@ -37376,7 +37539,7 @@ msgstr "一盒小鋼球。幾乎沒有殺傷力。" #: data/json/items/ammo.json msgid "feather" msgid_plural "feathers" -msgstr[0] "" +msgstr[0] "羽毛" #. ~ Description for {'str': 'feather'} #: data/json/items/ammo.json @@ -37386,7 +37549,7 @@ msgstr "一隻鳥的羽毛, 可以用來製作箭矢。" #: data/json/items/ammo.json msgid "down feather" msgid_plural "down feathers" -msgstr[0] "" +msgstr[0] "絨羽" #. ~ Description for {'str': 'down feather'} #: data/json/items/ammo.json @@ -37396,7 +37559,7 @@ msgstr "一隻鳥的蓬鬆羽絨, 可以用來製作舒適的被褥。" #: data/json/items/ammo.json msgid "120mm HEAT" msgid_plural "120mm HEATs" -msgstr[0] "" +msgstr[0] "120mm 高爆反坦克彈" #. ~ Description for {'str': '120mm HEAT'} #: data/json/items/ammo.json @@ -37407,7 +37570,7 @@ msgstr "一顆 120mm 反坦克高爆彈, 它可以摧毀任何東西。" #: data/json/items/ammo.json msgid "hydrogen canister" msgid_plural "hydrogen canisters" -msgstr[0] "" +msgstr[0] "固態氫罐" #. ~ Description for {'str': 'hydrogen canister'} #: data/json/items/ammo.json @@ -37419,7 +37582,7 @@ msgstr "能將氫氣壓縮成固體的鋼瓶。有正確的設備就能加熱成 #: data/json/items/ammo.json msgid "smokeless gunpowder" msgid_plural "smokeless gunpowders" -msgstr[0] "" +msgstr[0] "無煙型火藥" #. ~ Description for {'str': 'smokeless gunpowder'} #: data/json/items/ammo.json @@ -37429,7 +37592,7 @@ msgstr "火器级品质的火药。" #: data/json/items/ammo.json msgid "oxidizer powder" msgid_plural "oxidizer powders" -msgstr[0] "" +msgstr[0] "氧化劑粉" #. ~ Description for {'str': 'oxidizer powder'} #: data/json/items/ammo.json @@ -37439,7 +37602,7 @@ msgstr "揮發性粉狀化學氧化劑。" #: data/json/items/ammo.json msgid "lye powder" msgid_plural "lye powders" -msgstr[0] "" +msgstr[0] "鹼粉" #. ~ Description for {'str': 'lye powder'} #: data/json/items/ammo.json @@ -37449,7 +37612,7 @@ msgstr "粉末狀苛性鈉。" #: data/json/items/ammo.json msgid "shotgun primer" msgid_plural "shotgun primers" -msgstr[0] "" +msgstr[0] "霰彈底火" #. ~ Description for {'str': 'shotgun primer'} #: data/json/items/ammo.json @@ -37459,7 +37622,7 @@ msgstr "霰彈的底火。" #: data/json/items/ammo.json msgid "small pistol primer" msgid_plural "small pistol primers" -msgstr[0] "" +msgstr[0] "小口徑手槍子彈底火" #. ~ Description for {'str': 'small pistol primer'} #: data/json/items/ammo.json @@ -37469,7 +37632,7 @@ msgstr "小口徑手槍子彈的底火。" #: data/json/items/ammo.json msgid "large pistol primer" msgid_plural "large pistol primers" -msgstr[0] "" +msgstr[0] "大口徑手槍子彈底火" #. ~ Description for {'str': 'large pistol primer'} #: data/json/items/ammo.json @@ -37479,7 +37642,7 @@ msgstr "大口徑手槍子彈的底火。" #: data/json/items/ammo.json msgid "small rifle primer" msgid_plural "small rifle primers" -msgstr[0] "" +msgstr[0] "小口徑步槍子彈底火" #. ~ Description for {'str': 'small rifle primer'} #: data/json/items/ammo.json @@ -37489,7 +37652,7 @@ msgstr "小口徑步槍子彈的底火。" #: data/json/items/ammo.json msgid "large rifle primer" msgid_plural "large rifle primers" -msgstr[0] "" +msgstr[0] "大口徑步槍子彈底火" #. ~ Description for {'str': 'large rifle primer'} #: data/json/items/ammo.json @@ -37499,7 +37662,7 @@ msgstr "大口徑步槍子彈的底火。" #: data/json/items/ammo.json msgid "rubber slug" msgid_plural "rubber slugs" -msgstr[0] "" +msgstr[0] "橡膠彈頭" #. ~ Description for {'str': 'rubber slug'} #: data/json/items/ammo.json @@ -37521,7 +37684,7 @@ msgstr "一大塊有用的橡膠,可以很容易地塑型。" #: data/json/items/ammo.json msgid "copper" msgid_plural "coppers" -msgstr[0] "" +msgstr[0] "銅塊" #. ~ Description for {'str': 'copper'} #: data/json/items/ammo.json @@ -37533,7 +37696,7 @@ msgstr "一些銅碎。能夠用來製作一些有用的東西, 例如粗製的 #: data/json/items/ammo.json msgid "medical tape" msgid_plural "medical tapes" -msgstr[0] "" +msgstr[0] "醫用膠帶" #. ~ Description for {'str': 'medical tape'} #: data/json/items/ammo.json @@ -37543,7 +37706,7 @@ msgstr "一捆醫療用的膠帶, 類似大力膠帶。" #: data/json/items/ammo.json msgid "placeholder ammunition" msgid_plural "placeholder ammunitions" -msgstr[0] "" +msgstr[0] "占位用彈藥" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "charcoal" @@ -37573,7 +37736,7 @@ msgstr "焦炭和石灰的粉末混合物,可以在電弧爐中熔煉成可用 #: data/json/items/ammo.json msgid "coal" msgid_plural "coals" -msgstr[0] "" +msgstr[0] "煤炭" #. ~ Description for {'str': 'coal'} #: data/json/items/ammo.json @@ -37585,7 +37748,7 @@ msgstr "易燃的黑色碳塊, 通常用於烹飪與加熱。" #: data/json/items/ammo.json msgid "RA21E medical ampoule" msgid_plural "RA21E medical ampoules" -msgstr[0] "" +msgstr[0] "RA21E 醫用安瓿" #. ~ Description for {'str': 'RA21E medical ampoule'} #: data/json/items/ammo.json @@ -37598,7 +37761,7 @@ msgstr "一個玻璃小瓶, 裝有能快速癒合傷口的先進化學物質。 #: data/json/items/ammo.json msgid "RA10K stimulant module" msgid_plural "RA10K stimulant modules" -msgstr[0] "" +msgstr[0] "RA10K 興奮劑" #. ~ Description for {'str': 'RA10K stimulant module'} #: data/json/items/ammo.json @@ -37611,7 +37774,7 @@ msgstr "一種加壓多室玻璃小瓶, 其中充滿了強大的化學刺激劑 #: data/json/items/ammo.json msgid "rebreather filter cartridge" msgid_plural "rebreather filter cartridges" -msgstr[0] "" +msgstr[0] "呼吸器濾芯" #. ~ Description for {'str': 'rebreather filter cartridge'} #: data/json/items/ammo.json @@ -37621,7 +37784,7 @@ msgstr "一個呼吸器面罩使用的濾芯。" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "filter mask cartridge" msgid_plural "filter mask cartridges" -msgstr[0] "" +msgstr[0] "過濾面罩濾芯" #. ~ Description for {'str': 'filter mask cartridge'} #: data/json/items/ammo.json @@ -37631,7 +37794,7 @@ msgstr "用於空氣過濾面罩的小型更換濾芯。" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "gas mask cartridge" msgid_plural "gas mask cartridges" -msgstr[0] "" +msgstr[0] "防毒面具濾芯" #. ~ Description for {'str': 'gas mask cartridge'} #: data/json/items/ammo.json @@ -37641,7 +37804,7 @@ msgstr "用於空氣過濾面罩的中型更換濾芯。" #: data/json/items/ammo.json msgid "chemical mask cartridge" msgid_plural "chemical mask cartridges" -msgstr[0] "" +msgstr[0] "防化服面具濾芯" #. ~ Description for {'str': 'chemical mask cartridge'} #: data/json/items/ammo.json @@ -37651,7 +37814,7 @@ msgstr "用於空氣過濾面罩的大型更換濾芯。" #: data/json/items/ammo.json msgid "nicotine liquid" msgid_plural "nicotine liquids" -msgstr[0] "" +msgstr[0] "尼古丁濃縮液" #. ~ Description for {'str': 'nicotine liquid'} #: data/json/items/ammo.json @@ -37663,7 +37826,7 @@ msgstr "由丙二醇, 植物甘油, 調味劑和尼古丁組成的液體。" #: data/json/items/ammo.json data/json/items/ammo_types.json msgid "fish bait" msgid_plural "fish baits" -msgstr[0] "" +msgstr[0] "魚餌" #. ~ Description for {'str': 'fish bait'} #: data/json/items/ammo.json @@ -37673,7 +37836,7 @@ msgstr "一個用於捕魚陷阱的魚餌。" #: data/json/items/ammo.json msgid "spiked homemade rocket" msgid_plural "spiked homemade rockets" -msgstr[0] "" +msgstr[0] "自製尖刺火箭彈" #. ~ Description for {'str': 'spiked homemade rocket'} #: data/json/items/ammo.json @@ -37907,7 +38070,7 @@ msgstr ".38" #: data/json/items/ammo_types.json data/json/items/ammo/38super.json msgid ".38 Super" msgid_plural ".38 Supers" -msgstr[0] "" +msgstr[0] ".38 超級彈" #: data/json/items/ammo_types.json msgid ".40" @@ -37977,12 +38140,12 @@ msgstr "7.62x51mm" #: data/json/items/ammo_types.json data/json/items/ammo/40x46mm.json msgid "40x46mm grenade" msgid_plural "40x46mm grenades" -msgstr[0] "" +msgstr[0] "40x46mm 榴彈" #: data/json/items/ammo_types.json data/json/items/ammo/40x53mm.json msgid "40x53mm grenade" msgid_plural "40x53mm grenades" -msgstr[0] "" +msgstr[0] "40x53mm 榴彈" #: data/json/items/ammo_types.json msgid "high-explosive anti-tank warhead" @@ -38028,7 +38191,7 @@ msgstr[0] "機油" #: data/json/items/chemicals_and_resources.json msgid "anesthetic" msgid_plural "anesthetics" -msgstr[0] "" +msgstr[0] "麻醉劑" #: data/json/items/ammo_types.json msgid "soap" @@ -38069,7 +38232,7 @@ msgstr "高濃度酒精" #: data/json/items/ammo_types.json data/json/items/ammo/8x40mm.json msgid "8x40mm caseless" msgid_plural "8x40mm caseless" -msgstr[0] "" +msgstr[0] "8x40mm 無殼彈" #: data/json/items/ammo_types.json msgid "20x66mm caseless shotgun" @@ -38082,7 +38245,7 @@ msgstr "5x50mm 鋼鏢彈" #: data/json/items/ammo_types.json data/json/items/ammo/signal_flare.json msgid "signal flare" msgid_plural "signal flares" -msgstr[0] "" +msgstr[0] "信號彈" #: data/json/items/ammo_types.json msgid "powdered calcium carbide premix" @@ -38142,7 +38305,7 @@ msgstr "7.62x25mm" #: data/mods/Generic_Guns/ammo/black_powder.json msgid "paper cartridge" msgid_plural "paper cartridges" -msgstr[0] "" +msgstr[0] "紙卷彈" #: data/json/items/ammo_types.json msgid ".36 cap & ball" @@ -38193,7 +38356,7 @@ msgstr[0] "生乳" #: data/json/items/ammo_types.json data/json/items/ammo/paintball.json msgid "paintball" msgid_plural "paintballs" -msgstr[0] "" +msgstr[0] "漆彈" #: data/json/items/ammo_types.json msgid "compressed air" @@ -38208,7 +38371,7 @@ msgstr[0] "烏洛托品" #: data/json/items/ammo_types.json data/json/items/ammo/300blk.json msgid ".300 AAC Blackout" msgid_plural ".300 AAC Blackouts" -msgstr[0] "" +msgstr[0] ".300 BLK 彈" #: data/json/items/ammo_types.json data/json/items/comestibles/drink.json msgid "water" @@ -38307,7 +38470,7 @@ msgstr "這是一個適用於所有小型裝置的小型電池,不過它仍保 #: data/json/items/battery.json msgid "ultra-light plutonium battery" msgid_plural "ultra-light plutonium batteries" -msgstr[0] "" +msgstr[0] "超輕型鈽燃料電池" #. ~ Description for {'str': 'ultra-light plutonium battery', 'str_pl': #. 'ultra-light plutonium batteries'} @@ -38362,7 +38525,7 @@ msgstr "這是一個高容量的輕型電池,適用於所有類型的小型裝 #: data/json/items/battery.json msgid "light plutonium battery" msgid_plural "light plutonium batteries" -msgstr[0] "" +msgstr[0] "輕型鈽燃料電池" #. ~ Description for {'str': 'light plutonium battery', 'str_pl': 'light #. plutonium batteries'} @@ -38417,7 +38580,7 @@ msgstr "這是一個高容量的中型電池,適用於所有類型的器具和 #: data/json/items/battery.json msgid "medium plutonium battery" msgid_plural "medium plutonium batteries" -msgstr[0] "" +msgstr[0] "中型鈽燃料電池" #. ~ Description for {'str': 'medium plutonium battery', 'str_pl': 'medium #. plutonium batteries'} @@ -38472,7 +38635,7 @@ msgstr "這是一個高容量的重型的電池,適用於所有類型的工業 #: data/json/items/battery.json msgid "heavy plutonium battery" msgid_plural "heavy plutonium batteries" -msgstr[0] "" +msgstr[0] "重型鈽燃料電池" #. ~ Description for {'str': 'heavy plutonium battery', 'str_pl': 'heavy #. plutonium batteries'} @@ -38489,7 +38652,7 @@ msgstr "" #: data/json/items/battery.json msgid "military plutonium fuel cell" msgid_plural "military plutonium fuel cells" -msgstr[0] "" +msgstr[0] "軍用鈽燃料電池" #. ~ Description for {'str': 'military plutonium fuel cell'} #: data/json/items/battery.json @@ -38524,7 +38687,7 @@ msgstr[0] "抽象生化插件" #: data/json/items/bionics.json msgid "abstract bionic module (npc usable)" msgid_plural "abstract bionic modules (npc usable)" -msgstr[0] "" +msgstr[0] "虛擬生化插件(NPC可用)" #: data/json/items/bionics.json msgid "abstract faulty bionic module" @@ -38892,7 +39055,7 @@ msgstr "一对钻石角膜,能够极大提高用户的视力。感知+2。" #: data/json/items/bionics.json msgid "Telescopic Lenses CBM" msgid_plural "Telescopic Lenses CBMs" -msgstr[0] "" +msgstr[0] "CBM: 自動對焦眼球" #. ~ Description for {'str': 'Telescopic Lenses CBM'} #: data/json/items/bionics.json @@ -39107,7 +39270,7 @@ msgstr "这个生化激励系统增强了受体的造血系统,使其能够消 #: data/json/items/bionics.json msgid "Finger Lighter CBM" msgid_plural "Finger Lighter CBMs" -msgstr[0] "" +msgstr[0] "CBM: 手指打火機" #. ~ Description for {'str': 'Finger Lighter CBM'} #: data/json/items/bionics.json @@ -39960,7 +40123,7 @@ msgstr[0] "永久发电机CBM" #: data/json/items/biosignatures.json msgid "bird litter" msgid_plural "bird litter" -msgstr[0] "" +msgstr[0] "鳥糞" #. ~ Description for {'str_sp': 'bird litter'} #: data/json/items/biosignatures.json @@ -39970,7 +40133,7 @@ msgstr "鳥糞、羽毛和髒污的垃圾。" #: data/json/items/biosignatures.json msgid "cow pie" msgid_plural "cow pies" -msgstr[0] "" +msgstr[0] "牛糞" #. ~ Description for cow pie #: data/json/items/biosignatures.json @@ -39980,7 +40143,7 @@ msgstr "一坨新鮮的牛糞, 不只可用來插鮮花, 還可用來製作一 #: data/json/items/biosignatures.json msgid "dog dung" msgid_plural "dog dungs" -msgstr[0] "" +msgstr[0] "狗糞" #. ~ Description for dog dung #: data/json/items/biosignatures.json @@ -39990,7 +40153,7 @@ msgstr "來自犬類的糞便。" #: data/json/items/biosignatures.json msgid "manure" msgid_plural "manures" -msgstr[0] "" +msgstr[0] "糞便" #. ~ Description for manure #: data/json/items/biosignatures.json @@ -40000,7 +40163,7 @@ msgstr "一般糞便, 可用來製作一些肥料。" #: data/json/items/biosignatures.json msgid "roach dirt" msgid_plural "roach dirts" -msgstr[0] "" +msgstr[0] "蟑螂糞" #. ~ Description for roach dirt #: data/json/items/biosignatures.json @@ -40010,7 +40173,7 @@ msgstr "大塊黑色顆粒的腐爛物質。" #: data/json/items/biosignatures.json msgid "fetid goop" msgid_plural "fetid goops" -msgstr[0] "" +msgstr[0] "惡臭黏液" #. ~ Description for {'str': 'fetid goop'} #: data/json/items/biosignatures.json @@ -40238,7 +40401,7 @@ msgstr "加了鹽的水。不適合飲用。" #: data/json/items/chemicals_and_resources.json msgid "soapy water" msgid_plural "soapy water" -msgstr[0] "" +msgstr[0] "肥皂水" #. ~ Description for {'str_sp': 'soapy water'} #: data/json/items/chemicals_and_resources.json @@ -40282,7 +40445,7 @@ msgstr "濃酸。別喝。" #: data/json/items/chemicals_and_resources.json msgid "sewage sample" msgid_plural "sewage samples" -msgstr[0] "" +msgstr[0] "污水樣本" #. ~ Description for sewage sample #: data/json/items/chemicals_and_resources.json @@ -40476,7 +40639,7 @@ msgstr "少量硝酸铵。这种白色结晶粉末通常用作肥料和炸药的 #: data/json/items/chemicals_and_resources.json msgid "ammonium nitrate pellets" msgid_plural "ammonium nitrate pellets" -msgstr[0] "" +msgstr[0] "硝酸氨顆粒" #. ~ Description for {'str_sp': 'ammonium nitrate pellets'} #: data/json/items/chemicals_and_resources.json @@ -40636,7 +40799,7 @@ msgstr "" #: data/json/items/chemicals_and_resources.json msgid "composition b" msgid_plural "composition b" -msgstr[0] "" +msgstr[0] "B炸藥" #. ~ Description for {'str_sp': 'composition b'} #: data/json/items/chemicals_and_resources.json @@ -40675,7 +40838,7 @@ msgstr "一大塊鋅和硫的混合物, 用強力膠黏在一起, 可以作為 #: data/json/items/chemicals_and_resources.json msgid "water purification tablet" msgid_plural "water purification tablets" -msgstr[0] "" +msgstr[0] "淨水藥片" #. ~ Description for water purification tablet #: data/json/items/chemicals_and_resources.json @@ -40742,7 +40905,7 @@ msgstr "這是液態氫氧化鈉。它具有很強的腐蝕性, 小心輕放。" #: data/json/items/chemicals_and_resources.json msgid "nanomaterial canister" msgid_plural "nanomaterial canisters" -msgstr[0] "" +msgstr[0] "納米材料罐" #. ~ Description for {'str': 'nanomaterial canister'} #: data/json/items/chemicals_and_resources.json @@ -40867,7 +41030,7 @@ msgstr "這是一個金屬格柵。它可以用作製造化學催化劑的框架 #: data/json/items/chemicals_and_resources.json msgid "cobalt-60 pellet" msgid_plural "cobalt-60 pellets" -msgstr[0] "" +msgstr[0] "鈷-60 顆粒" #. ~ Description for {'str': 'cobalt-60 pellet'} #: data/json/items/chemicals_and_resources.json @@ -40879,7 +41042,7 @@ msgstr "放射性物质,曾经是核工业设备的一部分。不过你还没 #: data/json/items/chemicals_and_resources.json msgid "wooden bead" msgid_plural "wooden beads" -msgstr[0] "" +msgstr[0] "木珠" #. ~ Description for {'str': 'wooden bead'} #: data/json/items/chemicals_and_resources.json @@ -40915,7 +41078,7 @@ msgstr "這是一個裝滿土壤的帆布袋。它可以用來建設簡單的路 #: data/json/items/chemicals_and_resources.json msgid "rennet" msgid_plural "rennet" -msgstr[0] "" +msgstr[0] "凝乳酶" #. ~ Description for {'str_sp': 'rennet'} #: data/json/items/chemicals_and_resources.json @@ -40927,7 +41090,7 @@ msgstr "用于凝结牛奶的酶,用于制作奶酪。传统上由反刍动物 #: data/json/items/chemicals_and_resources.json msgid "rosin" msgid_plural "rosins" -msgstr[0] "" +msgstr[0] "松香" #. ~ Description for {'str': 'rosin'} #: data/json/items/chemicals_and_resources.json @@ -40937,7 +41100,7 @@ msgstr "這是一塊黃色松香。用於焊接上" #: data/json/items/chemicals_and_resources.json msgid "acetylene" msgid_plural "acetylene" -msgstr[0] "" +msgstr[0] "乙炔" #. ~ Description for {'str_sp': 'acetylene'} #: data/json/items/chemicals_and_resources.json @@ -41078,7 +41241,7 @@ msgstr "一個有瓶蓋能封口的塑膠瓶, 能裝入 500 毫升的液體。" #: data/json/items/containers.json msgid "condiment bottle" msgid_plural "condiment bottles" -msgstr[0] "" +msgstr[0] "調味料瓶" #. ~ Description for {'str': 'condiment bottle'} #: data/json/items/containers.json @@ -41222,7 +41385,7 @@ msgstr "一個鋁製罐子, 通常裝過了可樂之類的東西。這罐已被 #: data/json/items/containers.json msgid "paper carton" msgid_plural "paper cartons" -msgstr[0] "" +msgstr[0] "紙桶" #. ~ Description for {'str': 'paper carton'} #: data/json/items/containers.json @@ -41234,7 +41397,7 @@ msgstr "由纸,铝和塑料层压制成的纸板盒,容积为半加仑。附 #: data/json/items/containers.json msgid "opened paper carton" msgid_plural "opened paper cartons" -msgstr[0] "" +msgstr[0] "紙桶(開)" #. ~ Description for {'str': 'opened paper carton'} #: data/json/items/containers.json @@ -41256,7 +41419,7 @@ msgstr "這是一袋真空包裝食品。" #: data/json/items/containers.json msgid "small tin can" msgid_plural "small tin cans" -msgstr[0] "" +msgstr[0] "小錫罐" #. ~ Description for {'str': 'small tin can'} #: data/json/items/containers.json @@ -41266,7 +41429,7 @@ msgstr "一个小型锡制罐子,就是装金枪鱼的那种。" #: data/json/items/containers.json msgid "small opened tin can" msgid_plural "small opened tin cans" -msgstr[0] "" +msgstr[0] "小錫罐(開)" #. ~ Description for {'str': 'small opened tin can'} #: data/json/items/containers.json @@ -41278,7 +41441,7 @@ msgstr "一个小型锡制罐子,就是装金枪鱼的那种。这个已经被 #: data/json/items/containers.json msgid "medium tin can" msgid_plural "medium tin cans" -msgstr[0] "" +msgstr[0] "中錫罐" #. ~ Description for {'str': 'medium tin can'} #: data/json/items/containers.json @@ -41288,7 +41451,7 @@ msgstr "一个中型锡制罐子,就是装汤水的那种。" #: data/json/items/containers.json msgid "medium opened tin can" msgid_plural "medium opened tin cans" -msgstr[0] "" +msgstr[0] "中錫罐(開)" #. ~ Description for {'str': 'medium opened tin can'} #: data/json/items/containers.json @@ -41709,7 +41872,7 @@ msgstr "一個紳士的汽球,一個一次性的生命預防器,一個不得 #: data/json/items/containers.json msgid "balloon" msgid_plural "balloons" -msgstr[0] "" +msgstr[0] "氣球" #. ~ Description for {'str': 'balloon'} #: data/json/items/containers.json @@ -41731,7 +41894,7 @@ msgstr "一个大型锡制罐子,就是装豆子的那种。能够容纳大量 #: data/json/items/containers.json msgid "large opened tin can" msgid_plural "large opened tin cans" -msgstr[0] "" +msgstr[0] "大錫罐(開)" #. ~ Description for {'str': 'large opened tin can'} #: data/json/items/containers.json @@ -41743,7 +41906,7 @@ msgstr "一个大型锡制罐子,就是装豆子的那种。这个已经被打 #: data/json/items/containers.json msgid "survival kit box" msgid_plural "survival kit boxes" -msgstr[0] "" +msgstr[0] "生存工具箱(開)" #. ~ Description for {'str': 'survival kit box', 'str_pl': 'survival kit #. boxes'} @@ -41766,7 +41929,7 @@ msgstr "愚蠢的玩意, 如果你看到它, 接下來一定會有一些壞事 #: data/json/items/fake.json msgid "teeth and claws" msgid_plural "teeth and claws" -msgstr[0] "" +msgstr[0] "牙齒和爪子" #: data/json/items/fake.json msgid "integrated toolset" @@ -41781,7 +41944,7 @@ msgstr[0] "生化護目鏡" #: data/json/items/fake.json msgid "autonomous surgical scalpels" msgid_plural "autonomous surgical scalpels" -msgstr[0] "" +msgstr[0] "全自動外科手術刀" #. ~ Description for {'str_sp': 'autonomous surgical scalpels'} #: data/json/items/fake.json @@ -41810,12 +41973,12 @@ msgstr "測試 aep_clairvoyance_plus 指標的物品。如果隨機生成了, #: data/json/items/fake.json msgid "acid spit gun" msgid_plural "acid spit guns" -msgstr[0] "" +msgstr[0] "射酸槍" #: data/json/items/fake.json msgid "reach bow" msgid_plural "reach bows" -msgstr[0] "" +msgstr[0] "測試用長弓" #: data/json/items/fake.json msgid "A test item that is both a ranged weapon and a reach weapon" @@ -41867,7 +42030,7 @@ msgstr "一把假枪,通过未知的推进方式以极高的速度发射出某 #: data/json/items/fake.json msgid "grid water purifier" msgid_plural "grid water purifiers" -msgstr[0] "" +msgstr[0] "淨水器(電網)" #: data/json/items/faults_bionic.json msgid "Non-sterile" @@ -41964,7 +42127,7 @@ msgstr "適合用在化學反應上的純酒精 (約 95%)。你可以兌水喝 #: data/json/items/fuel.json msgid "denatured alcohol" msgid_plural "denatured alcohols" -msgstr[0] "" +msgstr[0] "工業酒精" #. ~ Description for {'str': 'denatured alcohol'} #: data/json/items/fuel.json @@ -41979,7 +42142,7 @@ msgstr "" #: data/json/items/fuel.json msgid "methanol" msgid_plural "methanols" -msgstr[0] "" +msgstr[0] "甲醇" #. ~ Description for {'str': 'methanol'} #: data/json/items/fuel.json @@ -41997,7 +42160,7 @@ msgstr "柴油。汽油提煉過程中的副產物。" #: data/json/items/fuel.json msgid "JP8 fuel" msgid_plural "JP8 fuel" -msgstr[0] "" +msgstr[0] "JP8 燃料" #. ~ Description for {'str_sp': 'JP8 fuel'} #: data/json/items/fuel.json @@ -42009,7 +42172,7 @@ msgstr "一种基于煤油制成的燃料,主要被美国军用载具用作柴 #: data/json/items/fuel.json msgid "avgas fuel" msgid_plural "avgas fuel" -msgstr[0] "" +msgstr[0] "航空燃油" #. ~ Description for {'str_sp': 'avgas fuel'} #: data/json/items/fuel.json @@ -42099,7 +42262,7 @@ msgstr "又大又重的冰柜,用于餐馆、大型商店和其他需要大量 #: data/json/items/furniture.json msgid "glass refrigerator" msgid_plural "glass refrigerators" -msgstr[0] "" +msgstr[0] "玻璃冰箱" #. ~ Description for glass refrigerator #: data/json/items/furniture.json @@ -42109,7 +42272,7 @@ msgstr "一个玻璃冰箱。用于在商店中展示冷冻商品。" #: data/json/items/furniture.json msgid "glass freezer" msgid_plural "glass freezers" -msgstr[0] "" +msgstr[0] "玻璃冰櫃" #. ~ Description for glass freezer #: data/json/items/furniture.json @@ -42124,27 +42287,27 @@ msgstr "一台家用电烤箱。" #: data/json/items/generic.json msgid "animal" msgid_plural "animal" -msgstr[0] "" +msgstr[0] "動物" #: data/json/items/generic.json msgid "nearby fire" msgid_plural "nearby fire" -msgstr[0] "" +msgstr[0] "靠近火源" #: data/json/items/generic.json msgid "muscle" msgid_plural "muscle" -msgstr[0] "" +msgstr[0] "肌肉" #: data/json/items/generic.json msgid "wind" msgid_plural "wind" -msgstr[0] "" +msgstr[0] "風速" #: data/json/items/generic.json msgid "sun light" msgid_plural "sun light" -msgstr[0] "" +msgstr[0] "陽光" #: data/json/items/generic.json msgid "metabolism" @@ -42159,7 +42322,7 @@ msgstr[0] "荒唐的能源" #: data/json/items/generic.json msgid "a smoking device and a source of flame" msgid_plural "a smoking device and a source of flames" -msgstr[0] "" +msgstr[0] "一個抽油煙裝置和火源" #: data/json/items/generic.json msgid "file" @@ -42272,7 +42435,7 @@ msgstr "一小塊諾梅克斯阻燃纖維。" #: data/json/items/generic.json msgid "superglue" msgid_plural "superglue" -msgstr[0] "" +msgstr[0] "萬能膠" #. ~ Description for {'str_sp': 'superglue'} #: data/json/items/generic.json @@ -42327,7 +42490,7 @@ msgstr "一件昆蟲的外骨骼, 輕又耐用。" #: data/json/items/generic.json msgid "set of 100 ceramic disk" msgid_plural "ceramic disks" -msgstr[0] "" +msgstr[0] "陶瓷盤套件" #. ~ Description for {'str': 'set of 100 ceramic disk', 'str_pl': 'ceramic #. disks'} @@ -42564,7 +42727,7 @@ msgstr "一條僵硬的鐵絲, 上面帶著銳利的刺。" #: data/json/items/generic.json msgid "steel mesh" msgid_plural "steel meshes" -msgstr[0] "" +msgstr[0] "鋼絲網" #. ~ Description for {'str': 'steel mesh', 'str_pl': 'steel meshes'} #: data/json/items/generic.json @@ -42723,7 +42886,7 @@ msgstr "用來把瓦斯器具點火的裝置, 通常伴隨著啪啪把火點燃 #: data/json/items/generic.json msgid "delayed fuze" msgid_plural "delayed fuzes" -msgstr[0] "" +msgstr[0] "延時引信" #. ~ Description for delayed fuze #: data/json/items/generic.json @@ -42735,7 +42898,7 @@ msgstr "一个结构复杂的机械引信。它似乎可以在触发后经过一 #: data/json/items/generic.json msgid "impact fuze" msgid_plural "impact fuzes" -msgstr[0] "" +msgstr[0] "撞擊引信" #. ~ Description for impact fuze #: data/json/items/generic.json @@ -42908,7 +43071,7 @@ msgstr "一台損毀的挖礦機器人, 基本上已經沒有威脅, 現在它 #: data/json/items/generic.json msgid "broken recon mech" msgid_plural "broken recon mechs" -msgstr[0] "" +msgstr[0] "偵察機甲(損壞)" #. ~ Description for {'str': 'broken recon mech'} #. ~ Description for {'str': 'broken mech lifter'} @@ -42920,17 +43083,17 @@ msgstr "这是一套损坏的机甲,看起来已经没法修了。" #: data/json/items/generic.json msgid "broken mech lifter" msgid_plural "broken mech lifters" -msgstr[0] "" +msgstr[0] "起重機甲(損壞)" #: data/json/items/generic.json msgid "broken combat mech" msgid_plural "broken combat mechs" -msgstr[0] "" +msgstr[0] "戰鬥機甲(損壞)" #: data/json/items/generic.json msgid "broken riot dispatch" msgid_plural "broken riot dispatches" -msgstr[0] "" +msgstr[0] "防暴派遣者(損壞)" #. ~ Description for {'str': 'broken riot dispatch', 'str_pl': 'broken riot #. dispatches'} @@ -42943,7 +43106,7 @@ msgstr "一台損毀的鎮暴母艦, 基本上已經沒有威脅了。它的 #: data/json/items/generic.json msgid "broken military dispatch" msgid_plural "broken military dispatches" -msgstr[0] "" +msgstr[0] "軍用派遣者(損壞)" #. ~ Description for {'str': 'broken military dispatch', 'str_pl': 'broken #. military dispatches'} @@ -43116,7 +43279,7 @@ msgstr "一個用於收訊的模組, 適合用於製作通訊設備。" #: data/json/items/generic.json msgid "large LCD screen" msgid_plural "large LCD screens" -msgstr[0] "" +msgstr[0] "大型液晶螢幕" #. ~ Description for {'str': 'large LCD screen'} #: data/json/items/generic.json @@ -43204,7 +43367,7 @@ msgstr "最先進的光學儲存系統,在細小的玻璃板上核著的微型 #: data/json/items/generic.json msgid "nanofabricator template (silicon photonics)" msgid_plural "nanofabricator templates (silicon photonics)" -msgstr[0] "" +msgstr[0] "納米製造模板(硅光子電路)" #. ~ Description for {'str': 'nanofabricator template (silicon photonics)', #. 'str_pl': 'nanofabricator templates (silicon photonics)'} @@ -43299,7 +43462,7 @@ msgstr "陶瓷裝甲板, 專門設計來用於防彈背心上。" #: data/json/items/generic.json msgid "fishbowl" msgid_plural "fishbowls" -msgstr[0] "" +msgstr[0] "玻璃魚缸" #. ~ Description for {'str': 'fishbowl'} #: data/json/items/generic.json @@ -43474,12 +43637,12 @@ msgstr "白色洋甘菊花,自古以來就被用作為草藥。" #: data/json/items/generic.json msgid "lotus flower" msgid_plural "lotus flowers" -msgstr[0] "" +msgstr[0] "荷花" #: data/json/items/generic.json msgid "spurge flowers" msgid_plural "spurge flowers" -msgstr[0] "" +msgstr[0] "大戟花" #. ~ Description for {'str_sp': 'spurge flowers'} #: data/json/items/generic.json @@ -43567,7 +43730,7 @@ msgstr "一团厚厚的泥巴糊,含沙量低,一旦干了就能减少碎裂 #: data/json/items/generic.json msgid "tanbark" msgid_plural "tanbark" -msgstr[0] "" +msgstr[0] "鞣料樹皮" #. ~ Description for {'str_sp': 'tanbark'} #: data/json/items/generic.json @@ -43587,7 +43750,7 @@ msgstr "一片既堅硬又防水的樹皮, 從樺樹上取得。" #: data/json/items/generic.json msgid "willowbark" msgid_plural "willowbark" -msgstr[0] "" +msgstr[0] "柳樹樹皮" #. ~ Description for {'str_sp': 'willowbark'} #: data/json/items/generic.json @@ -43609,7 +43772,7 @@ msgstr "一顆閃閃發光的鑽石。" #: data/json/items/generic.json msgid "garnet" msgid_plural "garnets" -msgstr[0] "" +msgstr[0] "石榴石" #. ~ Description for {'str': 'garnet'} #: data/json/items/generic.json @@ -43619,7 +43782,7 @@ msgstr "一颗闪闪发光的石榴石。" #: data/json/items/generic.json msgid "amethyst" msgid_plural "amethysts" -msgstr[0] "" +msgstr[0] "紫水晶" #. ~ Description for {'str': 'amethyst'} #: data/json/items/generic.json @@ -43629,7 +43792,7 @@ msgstr "一颗闪闪发光的紫水晶。" #: data/json/items/generic.json msgid "aquamarine" msgid_plural "aquamarines" -msgstr[0] "" +msgstr[0] "海藍寶石" #. ~ Description for {'str': 'aquamarine'} #: data/json/items/generic.json @@ -43639,7 +43802,7 @@ msgstr "一颗闪闪发光的海蓝宝石。" #: data/json/items/generic.json msgid "emerald" msgid_plural "emeralds" -msgstr[0] "" +msgstr[0] "祖母綠" #. ~ Description for {'str': 'emerald'} #: data/json/items/generic.json @@ -43649,7 +43812,7 @@ msgstr "一颗闪闪发光的祖母绿。" #: data/json/items/generic.json msgid "alexandrite" msgid_plural "alexandrites" -msgstr[0] "" +msgstr[0] "紫翠玉" #. ~ Description for {'str': 'alexandrite'} #: data/json/items/generic.json @@ -43659,7 +43822,7 @@ msgstr "一颗闪闪发光的紫翠玉。" #: data/json/items/generic.json msgid "pearl" msgid_plural "pearls" -msgstr[0] "" +msgstr[0] "珍珠" #. ~ Description for {'str': 'pearl'} #: data/json/items/generic.json @@ -43669,7 +43832,7 @@ msgstr "一颗光滑圆润的珍珠。" #: data/json/items/generic.json msgid "ruby" msgid_plural "rubies" -msgstr[0] "" +msgstr[0] "紅寶石" #. ~ Description for {'str': 'ruby', 'str_pl': 'rubies'} #: data/json/items/generic.json @@ -43679,7 +43842,7 @@ msgstr "一颗闪闪发光的红宝石。" #: data/json/items/generic.json msgid "peridot" msgid_plural "peridots" -msgstr[0] "" +msgstr[0] "橄欖石" #. ~ Description for {'str': 'peridot'} #: data/json/items/generic.json @@ -43689,7 +43852,7 @@ msgstr "一颗闪闪发光的橄榄石。" #: data/json/items/generic.json msgid "sapphire" msgid_plural "sapphires" -msgstr[0] "" +msgstr[0] "藍寶石" #. ~ Description for {'str': 'sapphire'} #: data/json/items/generic.json @@ -43699,7 +43862,7 @@ msgstr "一颗闪闪发光的蓝宝石。" #: data/json/items/generic.json msgid "opal" msgid_plural "opals" -msgstr[0] "" +msgstr[0] "蛋白石" #. ~ Description for {'str': 'opal'} #: data/json/items/generic.json @@ -43709,7 +43872,7 @@ msgstr "一颗光滑圆润的蛋白石。" #: data/json/items/generic.json msgid "tourmaline" msgid_plural "tourmalines" -msgstr[0] "" +msgstr[0] "電氣石" #. ~ Description for {'str': 'tourmaline'} #: data/json/items/generic.json @@ -43719,7 +43882,7 @@ msgstr "一颗闪闪发光的电气石。" #: data/json/items/generic.json msgid "citrine" msgid_plural "citrines" -msgstr[0] "" +msgstr[0] "黃水晶" #. ~ Description for {'str': 'citrine'} #: data/json/items/generic.json @@ -43729,7 +43892,7 @@ msgstr "一颗闪闪发光的黄水晶。" #: data/json/items/generic.json msgid "topaz" msgid_plural "topazs" -msgstr[0] "" +msgstr[0] "藍黃玉" #. ~ Description for {'str': 'topaz'} #: data/json/items/generic.json @@ -44092,7 +44255,7 @@ msgstr "這張 ID卡原本屬於某個高級技工,背面有記述使用的通 #: data/json/items/generic.json msgid "neoprene patch" msgid_plural "neoprene patches" -msgstr[0] "" +msgstr[0] "氯丁橡膠片" #. ~ Description for {'str': 'neoprene patch', 'str_pl': 'neoprene patches'} #: data/json/items/generic.json @@ -44151,7 +44314,7 @@ msgstr "一個有點過時的燈泡, 出現於各式燈光設備。" #: data/json/items/generic.json msgid "shrapnel" msgid_plural "shrapnels" -msgstr[0] "" +msgstr[0] "彈片" #. ~ Description for {'str': 'shrapnel'} #: data/json/items/generic.json @@ -44249,7 +44412,7 @@ msgstr "鋼製裝甲板,專門設計用於防彈背心" #: data/json/items/generic.json msgid "small lock and key" msgid_plural "small locks and keys" -msgstr[0] "" +msgstr[0] "小鎖和鑰匙" #. ~ Description for {'str': 'small lock and key', 'str_pl': 'small locks and #. keys'} @@ -44394,7 +44557,7 @@ msgstr "一套终极生存工具箱,可能是某个有钱人或是某个特别 #: data/json/items/generic.json msgid "plastic dice" msgid_plural "plastic dice" -msgstr[0] "" +msgstr[0] "塑膠骰子" #. ~ Description for {'str_sp': 'plastic dice'} #: data/json/items/generic.json @@ -44404,7 +44567,7 @@ msgstr "一个六面的塑料骰子。" #: data/json/items/generic.json msgid "salt lick" msgid_plural "salt licks" -msgstr[0] "" +msgstr[0] "舔鹽磚" #. ~ Description for {'str': 'salt lick'} #: data/json/items/generic.json @@ -44415,22 +44578,22 @@ msgstr "一大块沉重的立方体食盐块,供牲畜食用。别舔它,太 #: data/json/items/generic.json msgid "broken light turret" msgid_plural "broken light turrets" -msgstr[0] "" +msgstr[0] "輕型炮塔(損壞)" #: data/json/items/generic.json msgid "broken medium milspec turret" msgid_plural "broken medium milspec turrets" -msgstr[0] "" +msgstr[0] "中型軍用炮塔(損壞)" #: data/json/items/generic.json msgid "broken longrange milspec turret" msgid_plural "broken longrange milspec turrets" -msgstr[0] "" +msgstr[0] "長程軍用炮塔(損壞)" #: data/json/items/handloaded_bullets.json msgid "blunderbuss slug" msgid_plural "blunderbuss slugs" -msgstr[0] "" +msgstr[0] "火銃獨頭彈" #. ~ Description for {'str': 'blunderbuss slug'} #. ~ Description for {'str': 'blunderbuss, slug'} @@ -44443,7 +44606,7 @@ msgstr "一顆裝好的雷筒霰彈, 以一大塊金屬作為彈丸。適合遠 #: data/json/items/handloaded_bullets.json msgid "blunderbuss shot" msgid_plural "blunderbuss shots" -msgstr[0] "" +msgstr[0] "火銃霰彈" #. ~ Description for {'str': 'blunderbuss shot'} #. ~ Description for {'str': 'blunderbuss, shot'} @@ -44460,7 +44623,7 @@ msgstr "" #: data/json/items/handloaded_bullets.json msgid "blunderbuss flechette" msgid_plural "blunderbuss flechettes" -msgstr[0] "" +msgstr[0] "火銃鏢形彈" #. ~ Description for {'str': 'blunderbuss flechette'} #. ~ Description for {'str': 'blunderbuss, flechette'} @@ -44525,7 +44688,7 @@ msgstr "这个带鬼脸的塑料南瓜里面有一大根蜡烛。它无法提供 #: data/json/items/items_holiday.json msgid "yule wreath" msgid_plural "yule wreaths" -msgstr[0] "" +msgstr[0] "聖誕花環" #. ~ Description for {'str': 'yule wreath'} #: data/json/items/items_holiday.json @@ -44638,7 +44801,7 @@ msgstr "一份蜷曲帶有光澤的傳單, 似乎在宣傳一個大型地下都 #: data/json/items/newspaper.json msgid "note" msgid_plural "notes" -msgstr[0] "" +msgstr[0] "紙條" #: data/json/items/newspaper.json msgid "FEMA evacuation pamphlet" @@ -44731,7 +44894,7 @@ msgstr "廣距的傳感器組意味這能夠感知周遭的世界環境。" #: data/json/items/robot_parts.json msgid "self monitoring sensors" msgid_plural "self monitoring sensors" -msgstr[0] "" +msgstr[0] "自診斷傳感器" #. ~ Description for {'str_sp': 'self monitoring sensors'} #: data/json/items/robot_parts.json @@ -44862,7 +45025,7 @@ msgstr "一套小型的履帶,就像 Beagle 迷你坦克用的那樣。" #: data/json/items/robot_parts.json msgid "turret interior chassis" msgid_plural "turret interior chassis" -msgstr[0] "" +msgstr[0] "炮塔支架" #. ~ Description for {'str_sp': 'turret interior chassis'} #: data/json/items/robot_parts.json @@ -44896,12 +45059,12 @@ msgstr "移除所有部件後的人型機器人軀體。" #: data/json/items/software.json msgid "abstract autodoc installation data" msgid_plural "abstract autodoc installation datas" -msgstr[0] "" +msgstr[0] "虛擬全自動醫療儀安裝數據" #: data/json/items/software.json msgid "Alarm System CBM installation data" msgid_plural "Alarm System CBM installation data" -msgstr[0] "" +msgstr[0] "警報系統CBM安裝數據" #. ~ Description for {'str_sp': 'Alarm System CBM installation data'} #: data/json/items/software.json @@ -44917,7 +45080,7 @@ msgstr "" #: data/json/items/software.json msgid "LED Tattoo CBM installation data" msgid_plural "LED Tattoo CBM installation data" -msgstr[0] "" +msgstr[0] "LED紋身CBM安裝數據" #. ~ Description for {'str_sp': 'LED Tattoo CBM installation data'} #: data/json/items/software.json @@ -44933,7 +45096,7 @@ msgstr "" #: data/json/items/software.json msgid "Power Armor Interface CBM installation data" msgid_plural "Power Armor Interface CBM installation data" -msgstr[0] "" +msgstr[0] "外骨骼能源接口CBM安裝數據" #. ~ Description for {'str_sp': 'Power Armor Interface CBM installation data'} #: data/json/items/software.json @@ -44949,7 +45112,7 @@ msgstr "" #: data/json/items/software.json msgid "Power Storage CBM installation data" msgid_plural "Power Storage CBM installation data" -msgstr[0] "" +msgstr[0] "儲能模塊CBM安裝數據" #. ~ Description for {'str_sp': 'Power Storage CBM installation data'} #: data/json/items/software.json @@ -44965,7 +45128,7 @@ msgstr "" #: data/json/items/software.json msgid "Power Storage CBM Mk. II installation data" msgid_plural "Power Storage CBM Mk. II installation data" -msgstr[0] "" +msgstr[0] "Mk.II 型儲能模塊CBM安裝數據" #. ~ Description for {'str_sp': 'Power Storage CBM Mk. II installation data'} #: data/json/items/software.json @@ -44982,7 +45145,7 @@ msgstr "" #: data/json/items/software.json msgid "Internal Chronometer CBM installation data" msgid_plural "Internal Chronometer CBM installation data" -msgstr[0] "" +msgstr[0] "體內計時器CBM安裝數據" #. ~ Description for {'str_sp': 'Internal Chronometer CBM installation data'} #: data/json/items/software.json @@ -44998,7 +45161,7 @@ msgstr "" #: data/json/items/software.json msgid "Intravenous Needletip CBM installation data" msgid_plural "Intravenous Needletip CBM installation data" -msgstr[0] "" +msgstr[0] "靜脈輸液器CBM安裝數據" #. ~ Description for {'str_sp': 'Intravenous Needletip CBM installation data'} #: data/json/items/software.json @@ -45014,7 +45177,7 @@ msgstr "" #: data/json/items/software.json msgid "Blood Analysis CBM installation data" msgid_plural "Blood Analysis CBM installation data" -msgstr[0] "" +msgstr[0] "血液分析CBM安裝數據" #. ~ Description for {'str_sp': 'Blood Analysis CBM installation data'} #: data/json/items/software.json @@ -45030,7 +45193,7 @@ msgstr "" #: data/json/items/software.json msgid "Cranial Flashlight CBM installation data" msgid_plural "Cranial Flashlight CBM installation data" -msgstr[0] "" +msgstr[0] "腦殼手電CBM安裝數據" #. ~ Description for {'str_sp': 'Cranial Flashlight CBM installation data'} #: data/json/items/software.json @@ -45046,7 +45209,7 @@ msgstr "" #: data/json/items/software.json msgid "Electromagnetic Unit CBM installation data" msgid_plural "Electromagnetic Unit CBM installation data" -msgstr[0] "" +msgstr[0] "掌心電磁鐵CBM安裝數據" #. ~ Description for {'str_sp': 'Electromagnetic Unit CBM installation data'} #: data/json/items/software.json @@ -45062,7 +45225,7 @@ msgstr "" #: data/json/items/software.json msgid "Soporific Induction CBM installation data" msgid_plural "Soporific Induction CBM installation data" -msgstr[0] "" +msgstr[0] "催眠誘導CBM安裝數據" #. ~ Description for {'str_sp': 'Soporific Induction CBM installation data'} #: data/json/items/software.json @@ -45078,7 +45241,7 @@ msgstr "" #: data/json/items/software.json msgid "Arms Alloy Plating CBM installation data" msgid_plural "Arms Alloy Plating CBM installation data" -msgstr[0] "" +msgstr[0] "合金裝甲-手臂CBM安裝數據" #. ~ Description for {'str_sp': 'Arms Alloy Plating CBM installation data'} #: data/json/items/software.json @@ -45095,7 +45258,7 @@ msgstr "" #: data/json/items/software.json msgid "Legs Alloy Plating CBM installation data" msgid_plural "Legs Alloy Plating CBM installation data" -msgstr[0] "" +msgstr[0] "合金裝甲-腿部CBM安裝數據" #. ~ Description for {'str_sp': 'Legs Alloy Plating CBM installation data'} #: data/json/items/software.json @@ -45112,7 +45275,7 @@ msgstr "" #: data/json/items/software.json msgid "Shotgun Arm CBM installation data" msgid_plural "Shotgun Arm CBM installation data" -msgstr[0] "" +msgstr[0] "霰彈槍臂CBM安裝數據" #. ~ Description for {'str_sp': 'Shotgun Arm CBM installation data'} #: data/json/items/software.json @@ -45128,7 +45291,7 @@ msgstr "" #: data/json/items/software.json msgid "Blood Filter CBM installation data" msgid_plural "Blood Filter CBM installation data" -msgstr[0] "" +msgstr[0] "血液過濾CBM安裝數據" #. ~ Description for {'str_sp': 'Blood Filter CBM installation data'} #: data/json/items/software.json @@ -45144,7 +45307,7 @@ msgstr "" #: data/json/items/software.json msgid "Internal Climate Control CBM installation data" msgid_plural "Internal Climate Control CBM installation data" -msgstr[0] "" +msgstr[0] "恆溫機構CBM安裝數據" #. ~ Description for {'str_sp': 'Internal Climate Control CBM installation #. data'} @@ -45161,7 +45324,7 @@ msgstr "" #: data/json/items/software.json msgid "Integrated Dosimeter CBM installation data" msgid_plural "Integrated Dosimeter CBM installation data" -msgstr[0] "" +msgstr[0] "內置輻射計CBM安裝數據" #. ~ Description for {'str_sp': 'Integrated Dosimeter CBM installation data'} #: data/json/items/software.json @@ -45177,7 +45340,7 @@ msgstr "" #: data/json/items/software.json msgid "Thermal Dissipation CBM installation data" msgid_plural "Thermal Dissipation CBM installation data" -msgstr[0] "" +msgstr[0] "熱能防護CBM安裝數據" #. ~ Description for {'str_sp': 'Thermal Dissipation CBM installation data'} #: data/json/items/software.json @@ -45193,7 +45356,7 @@ msgstr "" #: data/json/items/software.json msgid "Weather Reader CBM installation data" msgid_plural "Weather Reader CBM installation data" -msgstr[0] "" +msgstr[0] "氣象識別CBM安裝數據" #. ~ Description for {'str_sp': 'Weather Reader CBM installation data'} #: data/json/items/software.json @@ -45209,7 +45372,7 @@ msgstr "" #: data/json/items/software.json msgid "Railgun CBM installation data" msgid_plural "Railgun CBM installation data" -msgstr[0] "" +msgstr[0] "磁軌步槍CBM安裝數據" #. ~ Description for {'str_sp': 'Railgun CBM installation data'} #: data/json/items/software.json @@ -45225,7 +45388,7 @@ msgstr "" #: data/json/items/software.json msgid "Unified Power System CBM installation data" msgid_plural "Unified Power System CBM installation data" -msgstr[0] "" +msgstr[0] "整合供能系統CBM安裝數據" #. ~ Description for {'str_sp': 'Unified Power System CBM installation data'} #: data/json/items/software.json @@ -45241,7 +45404,7 @@ msgstr "" #: data/json/items/software.json msgid "Titanium Skeletal Bracing CBM installation data" msgid_plural "Titanium Skeletal Bracing CBM installation data" -msgstr[0] "" +msgstr[0] "鈦合金骨架CBM安裝數據" #. ~ Description for {'str_sp': 'Titanium Skeletal Bracing CBM installation #. data'} @@ -45258,7 +45421,7 @@ msgstr "" #: data/json/items/software.json src/cata_tiles.cpp src/options.cpp msgid "software" msgid_plural "software" -msgstr[0] "" +msgstr[0] "軟體" #: data/json/items/software.json msgid "misc software" @@ -45374,7 +45537,7 @@ msgstr "一個用來將骨頭固定在位子上的工具。" #: data/json/items/tool_armor.json msgid "arm splint XL" msgid_plural "arm splints XL" -msgstr[0] "" +msgstr[0] "手臂夾板(XL)" #. ~ Description for {'str': 'arm splint XL', 'str_pl': 'arm splints XL'} #: data/json/items/tool_armor.json @@ -45439,7 +45602,7 @@ msgstr[0] "腿夾板" #: data/json/items/tool_armor.json msgid "leg splint XL" msgid_plural "leg splints XL" -msgstr[0] "" +msgstr[0] "腿骨夾板(XL)" #. ~ Description for {'str': 'leg splint XL', 'str_pl': 'leg splints XL'} #: data/json/items/tool_armor.json @@ -45528,7 +45691,7 @@ msgstr "一种带有深黑色视窗的塑料面罩,用来在焊接时保护整 #: data/json/items/tool_armor.json msgid "crude welding mask" msgid_plural "crude welding masks" -msgstr[0] "" +msgstr[0] "簡易焊接面具" #. ~ Description for {'str': 'crude welding mask'} #: data/json/items/tool_armor.json @@ -45541,7 +45704,7 @@ msgstr "一种用成形钢制成的简易焊接面罩。比真正的焊接面罩 #: data/json/items/tool_armor.json msgid "crude welding mask (raised)" msgid_plural "crude welding masks (raised)" -msgstr[0] "" +msgstr[0] "簡易焊接面具(升起)" #. ~ Use action menu_text for {'str': 'crude welding mask (raised)', 'str_pl': #. 'crude welding masks (raised)'}. @@ -45569,7 +45732,7 @@ msgstr "一种用成形钢制成的简易焊接面罩。比真正的焊接面罩 #: data/json/items/tool_armor.json msgid "welding mask (raised)" msgid_plural "welding masks (raised)" -msgstr[0] "" +msgstr[0] "焊接面具(升起)" #. ~ Use action msg for {'str': 'welding mask (raised)', 'str_pl': 'welding #. masks (raised)'}. @@ -45590,7 +45753,7 @@ msgstr "" #: data/json/items/tool_armor.json msgid "smart watch" msgid_plural "smart watches" -msgstr[0] "" +msgstr[0] "智慧手錶(UPS)" #. ~ Description for {'str': 'smart watch', 'str_pl': 'smart watches'} #: data/json/items/tool_armor.json @@ -45906,7 +46069,7 @@ msgstr "" #: data/json/items/tool_armor.json msgid "atomic headlamp" msgid_plural "atomic headlamps" -msgstr[0] "" +msgstr[0] "原子頭燈" #. ~ Use action menu_text for {'str': 'atomic headlamp'}. #. ~ Use action menu_text for {'str': 'atomic lamp'}. @@ -45935,7 +46098,7 @@ msgstr "" #: data/json/items/tool_armor.json msgid "atomic headlamp (covered)" msgid_plural "atomic headlamps (covered)" -msgstr[0] "" +msgstr[0] "原子頭燈 (蓋上)" #. ~ Use action menu_text for {'str': 'atomic headlamp (covered)', 'str_pl': #. 'atomic headlamps (covered)'}. @@ -46000,7 +46163,7 @@ msgstr "" #: data/json/items/tool_armor.json msgid "5-point anchor" msgid_plural "5-point anchors" -msgstr[0] "" +msgstr[0] "五點式空間錨" #. ~ Use action msg for {'str': '5-point anchor'}. #: data/json/items/tool_armor.json @@ -46022,7 +46185,7 @@ msgstr "一个装在背带上的无特征碟状装置。在它的正反两面分 #: data/json/items/tool_armor.json msgid "5-point anchor (on)" msgid_plural "5-point anchors (on)" -msgstr[0] "" +msgstr[0] "五點式空間錨(開)" #. ~ Use action msg for {'str': '5-point anchor (on)', 'str_pl': '5-point #. anchors (on)'}. @@ -46041,7 +46204,7 @@ msgstr "空间锚肩部的 LED 发出柔和的绿光。除此之外,似乎没 #: data/json/items/tool_armor.json msgid "phase immersion suit" msgid_plural "phase immersion suits" -msgstr[0] "" +msgstr[0] "相位沉浸服" #. ~ Use action msg for {'str': 'phase immersion suit'}. #: data/json/items/tool_armor.json @@ -46073,7 +46236,7 @@ msgstr "" #: data/json/items/tool_armor.json msgid "phase immersion suit (on)" msgid_plural "phase immersion suits (on)" -msgstr[0] "" +msgstr[0] "相位沉浸服(開)" #. ~ Use action msg for {'str': 'phase immersion suit (on)', 'str_pl': 'phase #. immersion suits (on)'}. @@ -47145,7 +47308,7 @@ msgstr "一件醫用工具。靠近物體並使用來進行聆聽。" #: data/json/items/tool_armor.json msgid "makeshift stethoscope" msgid_plural "makeshift stethoscopes" -msgstr[0] "" +msgstr[0] "簡易聽診器" #. ~ Description for {'str': 'makeshift stethoscope'} #: data/json/items/tool_armor.json @@ -47234,7 +47397,7 @@ msgstr "这是一个高压232巴的潜水罐,可以容纳多达12L的压缩氧 #: data/json/items/tool_armor.json msgid "scuba tank (on)" msgid_plural "scuba tanks (on)" -msgstr[0] "" +msgstr[0] "水肺氣瓶(開)" #: data/json/items/tool_armor.json msgid "small scuba tank" @@ -47254,7 +47417,7 @@ msgstr "这是一个小型的高压200巴备用潜水罐,可以容纳4L的压 #: data/json/items/tool_armor.json msgid "small scuba tank (on)" msgid_plural "small scuba tanks (on)" -msgstr[0] "" +msgstr[0] "小型水肺氣瓶(開)" #: data/json/items/tool_armor.json msgid "electric blanket" @@ -47444,7 +47607,7 @@ msgstr "電池盒模組,能使無法使用重型電池的工具轉換成使用 #: data/json/items/ammo/10mm.json msgid "10mm Auto FMJ" msgid_plural "10mm Auto FMJs" -msgstr[0] "" +msgstr[0] "10mm Auto 被甲彈" #. ~ Description for {'str': '10mm Auto FMJ'} #: data/json/items/ammo/10mm.json @@ -47456,12 +47619,12 @@ msgstr "金屬包覆的 10mm Auto 子彈。10mm Auto 子彈是相當強力的手 #: data/json/items/ammo/10mm.json msgid "10mm Auto FMJ, black powder" msgid_plural "10mm Auto FMJ, black powders" -msgstr[0] "" +msgstr[0] "10mm Auto 被甲彈(黑火藥)" #: data/json/items/ammo/12mm.json msgid "H&K 12mm" msgid_plural "H&K 12mms" -msgstr[0] "" +msgstr[0] "H&K 12mm彈" #. ~ Description for {'str': 'H&K 12mm'} #: data/json/items/ammo/12mm.json @@ -47473,7 +47636,7 @@ msgstr "用於 H&K 軌道槍的 12mm 彈藥。由磁性的金屬製成, 可能 #: data/json/items/ammo/20x66mm.json msgid "20x66mm beanbag" msgid_plural "20x66mm beanbags" -msgstr[0] "" +msgstr[0] "26X66mm 沙包彈" #. ~ Description for {'str': '20x66mm beanbag'} #: data/json/items/ammo/20x66mm.json @@ -47492,21 +47655,21 @@ msgstr[0] " 20x66mm 鋼鏢彈 (手工製)" #. flechettes, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless flechette rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "仿照 Rivtech 20x66mm 口徑無殼鋼鏢霰彈的手製品。作為無殼彈, 它不能夠被拆解或是重新組裝。" +"Handmade duplicates of Rivtech 20x66mm caseless flechette rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "手工制造的Rivtech的20x66mm 镖形弹,由于是无壳弹,所以不可拆解和复装。" #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot, handmade" msgid_plural "20x66mm buckshot, handmades" -msgstr[0] "" +msgstr[0] "26X66mm 獵鹿彈(自製)" #. ~ Description for {'str': '20x66mm buckshot, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless buckshot rounds." -" Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "仿照 Rivtech 20x66mm 口徑無殼獵鹿霰彈的手製品。作為無殼彈, 它不能夠被拆解或是重新組裝。" +"Handmade duplicates of Rivtech 20x66mm caseless buckshot rounds. Being " +"caseless rounds, these cannot be disassembled or reloaded." +msgstr "手工制造的Rivtech的20x66mm 猎鹿弹,由于是无壳弹,所以不可拆解和复装。" #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug, handmade" @@ -47517,14 +47680,14 @@ msgstr[0] "20x66mm獨頭彈 (手工製)" #. slugs, handmade'} #: data/json/items/ammo/20x66mm.json msgid "" -"Handcrafted bootleg duplicates of Rivtech 20x66mm caseless solid projectile " -"rounds. Being caseless rounds, these cannot be disassembled or reloaded." -msgstr "仿照 Rivtech 20x66mm 口徑無殼鋼彈頭的手製品。作為無殼彈, 它不能夠被拆解或是重新組裝。" +"Handmade duplicates of Rivtech 20x66mm caseless solid projectile rounds. " +"Being caseless rounds, these cannot be disassembled or reloaded." +msgstr "手工制造的Rivtech的20x66mm 合金弹,由于是无壳弹,所以不可拆解和复装。" #: data/json/items/ammo/20x66mm.json msgid "20x66mm explosive" msgid_plural "20x66mm explosives" -msgstr[0] "" +msgstr[0] "26X66mm 爆裂彈" #. ~ Description for {'str': '20x66mm explosive'} #: data/json/items/ammo/20x66mm.json @@ -47537,7 +47700,7 @@ msgstr "20x66mm 無殼霰彈, 此為高爆彈。Rivtech 霰彈槍的專屬彈藥 #: data/json/items/ammo/20x66mm.json msgid "20x66mm flare" msgid_plural "20x66mm flares" -msgstr[0] "" +msgstr[0] "26X66mm 信號彈" #. ~ Description for {'str': '20x66mm flare'} #: data/json/items/ammo/20x66mm.json @@ -47550,7 +47713,7 @@ msgstr "20x66mm 無殼霰彈, 此為信號彈。Rivtech 霰彈槍的專屬彈藥 #: data/json/items/ammo/20x66mm.json msgid "20x66mm flechette" msgid_plural "20x66mm flechettes" -msgstr[0] "" +msgstr[0] "26X66mm 鏢形彈" #. ~ Description for {'str': '20x66mm flechette'} #: data/json/items/ammo/20x66mm.json @@ -47563,7 +47726,7 @@ msgstr "20x66mm 無殼霰彈, 內含大量鋼鏢。Rivtech 霰彈槍的專屬彈 #: data/json/items/ammo/20x66mm.json msgid "20x66mm frag" msgid_plural "20x66mm frags" -msgstr[0] "" +msgstr[0] "26X66mm 榴彈" #. ~ Description for {'str': '20x66mm frag'} #: data/json/items/ammo/20x66mm.json @@ -47576,7 +47739,7 @@ msgstr "20x66mm 無殼霰彈, 此為破片爆裂彈。Rivtech 霰彈槍的專屬 #: data/json/items/ammo/20x66mm.json msgid "20x66mm incendiary" msgid_plural "20x66mm incendiaries" -msgstr[0] "" +msgstr[0] "26X66mm 燃燒彈" #. ~ Description for {'str': '20x66mm incendiary', 'str_pl': '20x66mm #. incendiaries'} @@ -47590,7 +47753,7 @@ msgstr "20x66mm 無殼霰彈, 此為燃燒彈。Rivtech 霰彈槍的專屬彈藥 #: data/json/items/ammo/20x66mm.json msgid "20x66mm buckshot" msgid_plural "20x66mm buckshots" -msgstr[0] "" +msgstr[0] "20x66mm 獵鹿彈" #. ~ Description for {'str': '20x66mm buckshot'} #: data/json/items/ammo/20x66mm.json @@ -47603,7 +47766,7 @@ msgstr "20x66mm 無殼霰彈, 此為獵鹿彈。Rivtech 霰彈槍的專屬彈藥 #: data/json/items/ammo/20x66mm.json msgid "20x66mm slug" msgid_plural "20x66mm slugs" -msgstr[0] "" +msgstr[0] "26X66mm 獨頭彈" #. ~ Description for {'str': '20x66mm slug'} #: data/json/items/ammo/20x66mm.json @@ -47616,7 +47779,7 @@ msgstr "20x66mm 無殼霰彈, 單顆全金屬彈頭設計。Rivtech 霰彈槍的 #: data/json/items/ammo/22.json msgid ".22 CPHP" msgid_plural ".22 CPHPs" -msgstr[0] "" +msgstr[0] ".22 鍍銅空尖彈" #. ~ Description for {'str': '.22 CPHP'} #: data/json/items/ammo/22.json @@ -47630,7 +47793,7 @@ msgstr "30格令的.22 长步枪镀铜空尖弹。与铅制圆头弹相比,它 #: data/json/items/ammo/22.json msgid ".22 LR" msgid_plural ".22 LRs" -msgstr[0] "" +msgstr[0] ".22 LR彈" #. ~ Description for {'str': '.22 LR'} #: data/json/items/ammo/22.json @@ -47645,7 +47808,7 @@ msgstr "" #: data/json/items/ammo/22.json msgid ".22 rat-shot" msgid_plural ".22 rat-shots" -msgstr[0] "" +msgstr[0] ".22 獵鼠彈" #. ~ Description for {'str': '.22 rat-shot'} #: data/json/items/ammo/22.json @@ -47658,12 +47821,12 @@ msgstr ".22 口徑霰彈內裝載著許多非常微小的彈丸, 並包覆於易 #: data/json/items/ammo/22.json msgid ".22 LR CPHP, black powder" msgid_plural ".22 LR CPHP, black powders" -msgstr[0] "" +msgstr[0] ".22 LR 鍍銅空尖彈(黑火藥)" #: data/json/items/ammo/22.json msgid ".22 LR, black powder" msgid_plural ".22 LR, black powders" -msgstr[0] "" +msgstr[0] ".22 LR 彈(黑火藥)" #: data/json/items/ammo/223.json msgid "5.56x45mm '.223 Remington'" @@ -47725,7 +47888,7 @@ msgstr[0] "5.56x45mm NATO 曳光弹(黑火药)" #: data/json/items/ammo/270win.json msgid ".270 Winchester JSP" msgid_plural ".270 Winchester JSPs" -msgstr[0] "" +msgstr[0] ".270 溫徹斯特軟尖彈" #. ~ Description for {'str': '.270 Winchester JSP'} #: data/json/items/ammo/270win.json @@ -47741,12 +47904,12 @@ msgstr "" #: data/json/items/ammo/270win.json msgid ".270 Winchester JSP, black powder" msgid_plural ".270 Winchester JSP, black powders" -msgstr[0] "" +msgstr[0] ".270 溫徹斯特軟尖彈(黑火藥)" #: data/json/items/ammo/300.json msgid ".300 Winchester Magnum" msgid_plural ".300 Winchester Magnums" -msgstr[0] "" +msgstr[0] ".300 溫徹斯特馬格南彈" #. ~ Description for {'str': '.300 Winchester Magnum'} #: data/json/items/ammo/300.json @@ -47762,12 +47925,12 @@ msgstr "" #: data/json/items/ammo/300.json msgid ".300 Winchester Magnum, black powder" msgid_plural ".300 Winchester Magnum, black powders" -msgstr[0] "" +msgstr[0] ".300 溫徹斯特馬格南彈(黑火藥)" #: data/json/items/ammo/3006.json msgid ".30-06 Springfield" msgid_plural ".30-06 Springfields" -msgstr[0] "" +msgstr[0] ".30-06 春田彈" #. ~ Description for {'str': '.30-06 Springfield'} #: data/json/items/ammo/3006.json @@ -47780,7 +47943,7 @@ msgstr "使用 165 格令軟質彈頭的 .30-06 春田彈。他極端的高準 #: data/json/items/ammo/3006.json msgid ".30-06 M14A1 tracer" msgid_plural ".30-06 M14A1 tracers" -msgstr[0] "" +msgstr[0] ".30-06 M14A1 曳光彈" #. ~ Description for {'str': '.30-06 M14A1 tracer'} #: data/json/items/ammo/3006.json @@ -47793,7 +47956,7 @@ msgstr ".30-06 M14A1 穿甲燃燒彈, 混入了曳光彈幫助使用者保持火 #: data/json/items/ammo/3006.json msgid ".30-06 M2 AP" msgid_plural ".30-06 M2 APs" -msgstr[0] "" +msgstr[0] ".30-06 M2 穿甲彈" #. ~ Description for {'str': '.30-06 M2 AP'} #: data/json/items/ammo/3006.json @@ -47806,17 +47969,17 @@ msgstr "使用 168 格令全金屬彈頭的 .30-06M2 穿甲彈。他是個極端 #: data/json/items/ammo/3006.json msgid ".30-06 Springfield, black powder" msgid_plural ".30-06 Springfield, black powders" -msgstr[0] "" +msgstr[0] ".30-06 春田彈(黑火藥)" #: data/json/items/ammo/3006.json msgid ".30-06 Springfield tracer, black powder" msgid_plural ".30-06 Springfield tracer, black powders" -msgstr[0] "" +msgstr[0] ".30-06 春田曳光彈(黑火藥)" #: data/json/items/ammo/3006.json msgid ".30-06 M2 AP, black powder" msgid_plural ".30-06 M2 AP, black powders" -msgstr[0] "" +msgstr[0] ".30-06 M2 穿甲彈(黑火藥)" #. ~ Description for {'str': '.300 AAC Blackout'} #: data/json/items/ammo/300blk.json @@ -47832,7 +47995,7 @@ msgstr "" #: data/json/items/ammo/300blk.json msgid ".300 AAC Blackout, subsonic" msgid_plural ".300 AAC Blackout, subsonics" -msgstr[0] "" +msgstr[0] ".300 BLK 亞音速彈" #. ~ Description for {'str': '.300 AAC Blackout, subsonic'} #: data/json/items/ammo/300blk.json @@ -47848,7 +48011,7 @@ msgstr "" #: data/json/items/ammo/300blk.json msgid ".300 AAC Blackout, black powder" msgid_plural ".300 AAC Blackout, black powders" -msgstr[0] "" +msgstr[0] ".300 BLK 彈(黑火藥)" #: data/json/items/ammo/308.json msgid "7.62x51mm '.308 Winchester'" @@ -47879,7 +48042,7 @@ msgstr "使用 147 格令全金屬彈頭的7.62x51mm NATO 彈。因為他的高 #: data/json/items/ammo/308.json msgid "7.62x51mm NATO tracer" msgid_plural "7.62x51mm NATO tracers" -msgstr[0] "" +msgstr[0] "7.62x51mm NATO 曳光彈" #. ~ Description for {'str': '7.62x51mm NATO tracer'} #: data/json/items/ammo/308.json @@ -47906,7 +48069,7 @@ msgstr[0] "7.62x51mm NATO 曳光弹(黑火药)" #: data/json/items/ammo/32.json msgid ".32 ACP" msgid_plural ".32 ACPs" -msgstr[0] "" +msgstr[0] ".32 ACP彈" #. ~ Description for {'str': '.32 ACP'} #: data/json/items/ammo/32.json @@ -47918,12 +48081,12 @@ msgstr ".32 ACP 是在 20 世紀流行的手槍子彈。但沒有 .38 或 9x19mm #: data/json/items/ammo/32.json msgid ".32 ACP, black powder" msgid_plural ".32 ACP, black powders" -msgstr[0] "" +msgstr[0] ".32 ACP 彈(黑火藥)" #: data/json/items/ammo/357mag.json msgid ".357 magnum FMJ" msgid_plural ".357 magnum FMJs" -msgstr[0] "" +msgstr[0] ".357 馬格南被甲彈" #. ~ Description for {'str': '.357 magnum FMJ'} #: data/json/items/ammo/357mag.json @@ -47936,7 +48099,7 @@ msgstr "金屬包覆的 .357 麥格農彈藥。這種 .357 麥格農子彈是源 #: data/json/items/ammo/357mag.json msgid ".357 magnum JHP" msgid_plural ".357 magnum JHPs" -msgstr[0] "" +msgstr[0] ".357 馬格南空尖彈" #. ~ Description for {'str': '.357 magnum JHP'} #: data/json/items/ammo/357mag.json @@ -47949,17 +48112,17 @@ msgstr "金屬包覆空尖彈頭的 .357 麥格農彈藥。這種 .357 麥格農 #: data/json/items/ammo/357mag.json msgid ".357 Magnum FMJ, black powder" msgid_plural ".357 Magnum FMJ, black powders" -msgstr[0] "" +msgstr[0] ".357 馬格南被甲彈(黑火藥)" #: data/json/items/ammo/357mag.json msgid ".357 Magnum JHP, black powder" msgid_plural ".357 Magnum JHP, black powders" -msgstr[0] "" +msgstr[0] ".357 馬格南空尖彈(黑火藥)" #: data/json/items/ammo/357sig.json msgid ".357 SIG FMJ" msgid_plural ".357 SIG FMJs" -msgstr[0] "" +msgstr[0] ".357 西格被甲彈" #. ~ Description for {'str': '.357 SIG FMJ'} #: data/json/items/ammo/357sig.json @@ -47971,7 +48134,7 @@ msgstr ".357 SIG 全金屬彈藥。 .357 SIG 是一種高速手槍彈,彈道 #: data/json/items/ammo/357sig.json msgid ".357 SIG JHP" msgid_plural ".357 SIG JHPs" -msgstr[0] "" +msgstr[0] ".357 西格空尖彈" #. ~ Description for {'str': '.357 SIG JHP'} #: data/json/items/ammo/357sig.json @@ -47984,7 +48147,7 @@ msgstr ".357 SIG 全金屬空心彈。 .357 SIG 是一種高速手槍彈,彈 #: data/json/items/ammo/36paper.json msgid ".36 paper cartridge" msgid_plural ".36 paper cartridges" -msgstr[0] "" +msgstr[0] ".36 紙卷彈" #. ~ Description for {'str': '.36 paper cartridge'} #: data/json/items/ammo/36paper.json @@ -47996,7 +48159,7 @@ msgstr "一個內含定量黑火藥與 .36 彈丸的紙卷子彈。適用於柯 #: data/json/items/ammo/38.json msgid ".38 FMJ" msgid_plural ".38 FMJs" -msgstr[0] "" +msgstr[0] ".38 被甲彈" #. ~ Description for {'str': '.38 FMJ'} #: data/json/items/ammo/38.json @@ -48008,7 +48171,7 @@ msgstr ".38 全金屬彈使用以黃銅包覆的 130 格令彈頭, 以高準繩 #: data/json/items/ammo/38.json msgid ".38 Special" msgid_plural ".38 Specials" -msgstr[0] "" +msgstr[0] ".38 特製彈" #. ~ Description for {'str': '.38 Special'} #: data/json/items/ammo/38.json @@ -48020,17 +48183,17 @@ msgstr ".38 特殊彈使用 130 格令彈頭, 全彈以金屬包覆。它在 20 #: data/json/items/ammo/38.json msgid ".38 FMJ, black powder" msgid_plural ".38 FMJ, black powders" -msgstr[0] "" +msgstr[0] ".38 被甲彈(黑火藥)" #: data/json/items/ammo/38.json msgid ".38 Special, black powder" msgid_plural ".38 Special, black powders" -msgstr[0] "" +msgstr[0] ".38 特製彈(黑火藥)" #: data/json/items/ammo/380.json msgid ".380 ACP FMJ" msgid_plural ".380 ACP FMJs" -msgstr[0] "" +msgstr[0] ".380 ACP 被甲彈" #. ~ Description for {'str': '.380 ACP FMJ'} #: data/json/items/ammo/380.json @@ -48046,7 +48209,7 @@ msgstr "" #: data/json/items/ammo/380.json msgid ".380 ACP JHP" msgid_plural ".380 ACP JHPs" -msgstr[0] "" +msgstr[0] ".380 ACP 空尖彈" #. ~ Description for {'str': '.380 ACP JHP'} #: data/json/items/ammo/380.json @@ -48062,7 +48225,7 @@ msgstr "" #: data/json/items/ammo/380.json msgid ".380 ACP +P" msgid_plural ".380 ACP +Ps" -msgstr[0] "" +msgstr[0] ".380 ACP +P彈" #. ~ Description for {'str': '.380 ACP +P'} #: data/json/items/ammo/380.json @@ -48079,17 +48242,17 @@ msgstr "" #: data/json/items/ammo/380.json msgid ".380 ACP FMJ, black powder" msgid_plural ".380 ACP FMJ, black powders" -msgstr[0] "" +msgstr[0] ".380 ACP 被甲彈(黑火藥)" #: data/json/items/ammo/380.json msgid ".380 ACP JHP, black powder" msgid_plural ".380 ACP JHP, black powders" -msgstr[0] "" +msgstr[0] ".380 ACP 空尖彈(黑火藥)" #: data/json/items/ammo/38super.json msgid ".38 Super FMJ" msgid_plural ".38 Super FMJs" -msgstr[0] "" +msgstr[0] ".38 超級被甲彈" #. ~ Description for {'str': '.38 Super FMJ'} #: data/json/items/ammo/38super.json @@ -48111,7 +48274,7 @@ msgstr ".38 超級彈使用 90 格令空尖彈頭。它誕生於1929年, 專用 #: data/json/items/ammo/40.json msgid ".40 S&W FMJ" msgid_plural ".40 S&W FMJs" -msgstr[0] "" +msgstr[0] ".40 S&W 被甲彈" #. ~ Description for {'str': '.40 S&W FMJ'} #: data/json/items/ammo/40.json @@ -48126,7 +48289,7 @@ msgstr "" #: data/json/items/ammo/40.json msgid ".40 S&W JHP" msgid_plural ".40 S&W JHPs" -msgstr[0] "" +msgstr[0] ".40 S&W 空尖彈" #. ~ Description for {'str': '.40 S&W JHP'} #: data/json/items/ammo/40.json @@ -48140,17 +48303,17 @@ msgstr "" #: data/json/items/ammo/40.json msgid ".40 S&W FMJ, black powder" msgid_plural ".40 S&W FMJ, black powders" -msgstr[0] "" +msgstr[0] ".40 S&W 被甲彈(黑火藥)" #: data/json/items/ammo/40.json msgid ".40 S&W JHP, black powder" msgid_plural ".40 S&W JHP, black powders" -msgstr[0] "" +msgstr[0] ".40 S&W 空尖彈(黑火藥)" #: data/json/items/ammo/40x46mm.json msgid "40x46mm M1006 stun" msgid_plural "40x46mm M1006 stuns" -msgstr[0] "" +msgstr[0] "40x46mm M1006 海綿彈" #. ~ Description for {'str': '40x46mm M1006 stun'} #: data/json/items/ammo/40x46mm.json @@ -48163,7 +48326,7 @@ msgstr "一款低初速低杀伤的40x46mm榴弹,弹头内装着泡沫和塑 #: data/json/items/ammo/40x46mm.json msgid "40x46mm M433 HEDP" msgid_plural "40x46mm M433 HEDPs" -msgstr[0] "" +msgstr[0] "40x46mm M433 高爆兩用彈" #. ~ Description for {'str': '40x46mm M433 HEDP'} #: data/json/items/ammo/40x46mm.json @@ -48176,7 +48339,7 @@ msgstr "一款低初速的40x46mm HEDP 高爆两用榴弹。它能够穿透2英 #: data/json/items/ammo/40x46mm.json msgid "40x46mm M576 buckshot" msgid_plural "40x46mm M576 buckshots" -msgstr[0] "" +msgstr[0] "40x46mm M576 獵鹿彈" #. ~ Description for {'str': '40x46mm M576 buckshot'} #: data/json/items/ammo/40x46mm.json @@ -48188,7 +48351,7 @@ msgstr "一款低初速的40x46mm猎鹿榴弹,设计供丛林和室内近距 #: data/json/items/ammo/40x46mm.json msgid "40x46mm M651 teargas" msgid_plural "40x46mm M651 teargass" -msgstr[0] "" +msgstr[0] "40x46mm M651 催淚彈" #. ~ Description for {'str': '40x46mm M651 teargas'} #: data/json/items/ammo/40x46mm.json @@ -48200,7 +48363,7 @@ msgstr "一款低初速的40x46mm催泪瓦斯榴弹。在防暴行动及将敌 #: data/json/items/ammo/40x46mm.json msgid "improvised 40x46mm buckshot" msgid_plural "improvised 40x46mm buckshots" -msgstr[0] "" +msgstr[0] "40x46mm 獵鹿彈(復裝)" #. ~ Description for {'str': 'improvised 40x46mm buckshot'} #: data/json/items/ammo/40x46mm.json @@ -48213,7 +48376,7 @@ msgstr "一颗自制的40x46mm猎鹿弹头榴弹,弹道特性接近于 M576 #: data/json/items/ammo/40x46mm.json msgid "improvised 40x46mm slug" msgid_plural "improvised 40x46mm slugs" -msgstr[0] "" +msgstr[0] "40x46mm 獨頭彈(復裝)" #. ~ Description for {'str': 'improvised 40x46mm slug'} #: data/json/items/ammo/40x46mm.json @@ -48234,7 +48397,7 @@ msgstr "一种复装的40x46mm子弹,类似于一个超大的霰弹枪子弹 #: data/json/items/ammo/40x46mm.json msgid "improvised 40x46mm flechette" msgid_plural "improvised 40x46mm flechettes" -msgstr[0] "" +msgstr[0] "40x46mm 鏢型彈(復裝)" #. ~ Description for {'str': 'improvised 40x46mm flechette'} #: data/json/items/ammo/40x46mm.json @@ -48255,7 +48418,7 @@ msgstr "一种复装的40x46mm镖型弹,装有70枚钢镖,这一种装在M57 #: data/json/items/ammo/40x53mm.json msgid "40x53mm M1001 flechette" msgid_plural "40x53mm M1001 flechettes" -msgstr[0] "" +msgstr[0] "40x53mm M1001 鏢形彈" #. ~ Description for {'str': '40x53mm M1001 flechette'} #: data/json/items/ammo/40x53mm.json @@ -48265,7 +48428,7 @@ msgstr "一款40x53mm镖形榴弹,弹头内装着17格令重的飞镖。" #: data/json/items/ammo/40x53mm.json msgid "40x53mm M430A1 HEDP" msgid_plural "40x53mm M430A1 HEDPs" -msgstr[0] "" +msgstr[0] "40x53mm M430A1 高爆兩用彈" #. ~ Description for {'str': '40x53mm M430A1 HEDP'} #: data/json/items/ammo/40x53mm.json @@ -48278,7 +48441,7 @@ msgstr "一款高初速的40x53mm HEDP 高爆两用榴弹。它能够穿透3英 #: data/json/items/ammo/40x53mm.json msgid "improvised 40x53mm buckshot" msgid_plural "improvised 40x53mm buckshots" -msgstr[0] "" +msgstr[0] "40x53mm 獵鹿彈(復裝)" #. ~ Description for {'str': 'improvised 40x53mm buckshot'} #: data/json/items/ammo/40x53mm.json @@ -48288,7 +48451,7 @@ msgstr "一款自制的40x53mm猎鹿榴弹,弹道特性接近于 M576 榴弹 #: data/json/items/ammo/40x53mm.json msgid "improvised 40x53mm slug" msgid_plural "improvised 40x53mm slugs" -msgstr[0] "" +msgstr[0] "40x53mm獨頭彈(復裝)" #. ~ Description for {'str': 'improvised 40x53mm slug'} #: data/json/items/ammo/40x53mm.json @@ -48298,7 +48461,7 @@ msgstr "一款自制的40x53mm独头榴弹,弹道特性接近于大号的独 #: data/json/items/ammo/410shot.json msgid ".410 000 shot" msgid_plural ".410 000 shots" -msgstr[0] "" +msgstr[0] ".410 000 號霰彈" #. ~ Description for {'str': '.410 000 shot'} #: data/json/items/ammo/410shot.json @@ -48308,7 +48471,7 @@ msgstr "裝有5000顆彈丸的 .410彈殼。非常適合狩獵或是戰鬥。" #: data/json/items/ammo/44.json msgid ".44 Magnum FMJ" msgid_plural ".44 Magnum FMJs" -msgstr[0] "" +msgstr[0] ".44 馬格南被甲彈" #. ~ Description for {'str': '.44 Magnum FMJ'} #: data/json/items/ammo/44.json @@ -48320,7 +48483,7 @@ msgstr ".44口径的马格南弹的黄铜全被甲改装型号,通过牺牲弹 #: data/json/items/ammo/44.json msgid ".44 Magnum" msgid_plural ".44 Magnums" -msgstr[0] "" +msgstr[0] ".44 馬格南彈" #. ~ Description for {'str': '.44 Magnum'} #: data/json/items/ammo/44.json @@ -48333,17 +48496,17 @@ msgstr ".44 麥格農子彈使用 240 格令空尖彈頭, 在手槍彈種中有 #: data/json/items/ammo/44.json msgid ".44 Magnum, black powder" msgid_plural ".44 Magnum, black powders" -msgstr[0] "" +msgstr[0] ".44 馬格南彈(黑火藥)" #: data/json/items/ammo/44.json msgid ".44 Magnum FMJ, black powder" msgid_plural ".44 Magnum FMJ, black powders" -msgstr[0] "" +msgstr[0] ".44 馬格南被甲彈(黑火藥)" #: data/json/items/ammo/44paper.json msgid ".44 paper cartridge" msgid_plural ".44 paper cartridges" -msgstr[0] "" +msgstr[0] ".44 紙卷彈" #. ~ Description for {'str': '.44 paper cartridge'} #: data/json/items/ammo/44paper.json @@ -48355,7 +48518,7 @@ msgstr "一個內含定量黑火藥與 .44 彈丸的紙卷子彈。適用於柯 #: data/json/items/ammo/45.json msgid ".45 ACP FMJ" msgid_plural ".45 ACP FMJs" -msgstr[0] "" +msgstr[0] ".45 ACP 被甲彈" #. ~ Description for {'str': '.45 ACP FMJ'} #: data/json/items/ammo/45.json @@ -48367,7 +48530,7 @@ msgstr ".45 ACP 全金屬彈使用 230 格令彈頭, 全彈以金屬包覆。.45 #: data/json/items/ammo/45.json msgid ".45 ACP JHP" msgid_plural ".45 ACP JHPs" -msgstr[0] "" +msgstr[0] ".45 ACP 空尖彈" #. ~ Description for {'str': '.45 ACP JHP'} #: data/json/items/ammo/45.json @@ -48382,7 +48545,7 @@ msgstr "" #: data/json/items/ammo/45.json msgid ".45 ACP +P" msgid_plural ".45 ACP +Ps" -msgstr[0] "" +msgstr[0] ".45 ACP +P彈" #. ~ Description for {'str': '.45 ACP +P'} #: data/json/items/ammo/45.json @@ -48395,17 +48558,17 @@ msgstr ".45 ACP 高壓彈使用 200 格令空尖彈頭。高壓彈擁有較高 #: data/json/items/ammo/45.json msgid ".45 ACP FMJ, black powder" msgid_plural ".45 ACP FMJ, black powders" -msgstr[0] "" +msgstr[0] ".45 ACP 被甲彈(黑火藥)" #: data/json/items/ammo/45.json msgid ".45 ACP JHP, black powder" msgid_plural ".45 ACP JHP, black powders" -msgstr[0] "" +msgstr[0] ".45 ACP 空尖彈(黑火藥)" #: data/json/items/ammo/454.json msgid ".454 Casull" msgid_plural ".454 Casulls" -msgstr[0] "" +msgstr[0] ".454 卡蘇爾彈" #. ~ Description for {'str': '.454 Casull'} #: data/json/items/ammo/454.json @@ -48422,12 +48585,12 @@ msgstr "" #: data/json/items/ammo/454.json msgid ".454 Casull, black powder" msgid_plural ".454 Casull, black powders" -msgstr[0] "" +msgstr[0] ".454 卡爾蘇彈(黑火藥)" #: data/json/items/ammo/4570.json msgid ".45-70 SP" msgid_plural ".45-70 SPs" -msgstr[0] "" +msgstr[0] ".45-70 SP彈" #. ~ Description for {'str': '.45-70 SP'} #: data/json/items/ammo/4570.json @@ -48440,7 +48603,7 @@ msgstr ".45-70 政府彈藥裝有 305 喱軟尖彈頭。這是目前仍在使用 #: data/json/items/ammo/4570.json msgid ".45-70 +P penetrator" msgid_plural ".45-70 +P penetrators" -msgstr[0] "" +msgstr[0] ".45-70 +P 穿甲彈" #. ~ Description for {'str': '.45-70 +P penetrator'} #: data/json/items/ammo/4570.json @@ -48453,7 +48616,7 @@ msgstr "使用 305 格令铜芯穿甲弹弹头的 .45-70政府弹。设计在最 #: data/json/items/ammo/4570.json msgid ".45-70 LFN cowboy" msgid_plural ".45-70 LFN cowboys" -msgstr[0] "" +msgstr[0] ".45-70 LFN 牛仔彈" #. ~ Description for {'str': '.45-70 LFN cowboy'} #: data/json/items/ammo/4570.json @@ -48467,7 +48630,7 @@ msgstr "" #: data/json/items/ammo/4570.json msgid ".45-70, black powder" msgid_plural ".45-70, black powders" -msgstr[0] "" +msgstr[0] ".45-70 彈(黑火藥)" #. ~ Description for {'str': '.45-70, black powder'} #: data/json/items/ammo/4570.json @@ -48483,7 +48646,7 @@ msgstr "" #: data/json/items/ammo/45colt.json msgid ".45 Colt JHP" msgid_plural ".45 Colt JHPs" -msgstr[0] "" +msgstr[0] ".45 柯爾特空尖彈" #. ~ Description for {'str': '.45 Colt JHP'} #: data/json/items/ammo/45colt.json @@ -48499,12 +48662,12 @@ msgstr "" #: data/json/items/ammo/45colt.json msgid ".45 Colt JHP, black powder" msgid_plural ".45 Colt JHP, black powders" -msgstr[0] "" +msgstr[0] ".45 柯爾特空尖彈(黑火藥)" #: data/json/items/ammo/46.json msgid "4.6x30mm" msgid_plural "4.6x30mms" -msgstr[0] "" +msgstr[0] "4.6x30mm 彈" #. ~ Description for {'str': '4.6x30mm'} #: data/json/items/ammo/46.json @@ -48519,7 +48682,7 @@ msgstr "" #: data/json/items/ammo/46.json msgid "4.6x30mm, black powder" msgid_plural "4.6x30mm, black powders" -msgstr[0] "" +msgstr[0] "4.6x30mm 彈(黑火藥)" #. ~ Description for {'str': '4.6x30mm, black powder'} #. ~ Description for {'str': '4.6x30mm, reloaded'} @@ -48536,7 +48699,7 @@ msgstr "" #: data/json/items/ammo/460.json msgid ".460 Rowland HCFN" msgid_plural ".460 Rowland HCFNs" -msgstr[0] "" +msgstr[0] ".460 羅蘭德平頭硬質彈" #. ~ Description for {'str': '.460 Rowland HCFN'} #: data/json/items/ammo/460.json @@ -48548,7 +48711,7 @@ msgstr "使用平頭彈頭的.460 羅蘭彈。藉由犧牲彈頭擴張性所帶 #: data/json/items/ammo/460.json msgid ".460 Rowland" msgid_plural ".460 Rowlands" -msgstr[0] "" +msgstr[0] ".460 羅蘭德彈" #. ~ Description for {'str': '.460 Rowland'} #: data/json/items/ammo/460.json @@ -48565,17 +48728,17 @@ msgstr "" #: data/json/items/ammo/460.json msgid ".460 Rowland FMJ, black powder" msgid_plural ".460 Rowland FMJ, black powders" -msgstr[0] "" +msgstr[0] ".460 羅蘭德被甲彈(黑火藥)" #: data/json/items/ammo/460.json msgid ".460 Rowland, black powder" msgid_plural ".460 Rowland, black powders" -msgstr[0] "" +msgstr[0] ".460 羅蘭德彈(黑火藥)" #: data/json/items/ammo/50.json msgid ".50 BMG M17 tracer" msgid_plural ".50 BMG M17 tracers" -msgstr[0] "" +msgstr[0] ".50 BMG M17 曳光彈" #. ~ Description for {'str': '.50 BMG M17 tracer'} #: data/json/items/ammo/50.json @@ -48588,7 +48751,7 @@ msgstr ".50 BMG 弹的曳光弹型号。曳光弹种可帮助保持对射击目 #: data/json/items/ammo/50.json msgid ".50 BMG M33 Ball" msgid_plural ".50 BMG M33 Balls" -msgstr[0] "" +msgstr[0] ".50 BMG M33 普通彈" #. ~ Description for {'str': '.50 BMG M33 Ball'} #: data/json/items/ammo/50.json @@ -48605,7 +48768,7 @@ msgstr "" #: data/json/items/ammo/50.json msgid ".50 BMG Match" msgid_plural ".50 BMG Matches" -msgstr[0] "" +msgstr[0] ".50 BMG 競賽彈" #. ~ Description for {'str': '.50 BMG Match', 'str_pl': '.50 BMG Matches'} #: data/json/items/ammo/50.json @@ -48617,7 +48780,7 @@ msgstr ".50 BMG 全金屬彈鉛芯彈藥以更精密的刻度製成,可用於 #: data/json/items/ammo/50.json msgid ".50 BMG M2 AP" msgid_plural ".50 BMG M2 APs" -msgstr[0] "" +msgstr[0] ".50 BMG M2 穿甲彈" #. ~ Description for {'str': '.50 BMG M2 AP'} #: data/json/items/ammo/50.json @@ -48629,7 +48792,7 @@ msgstr "改用密度及堅硬度極高的鎢鋼所製成的 .50 BMG 子彈。提 #: data/json/items/ammo/50.json msgid ".50 BMG Raufoss Mk 211" msgid_plural ".50 BMG Raufoss Mk 211s" -msgstr[0] "" +msgstr[0] ".50 BMG 諾霍斯 Mk 211 彈" #. ~ Description for {'str': '.50 BMG Raufoss Mk 211'} #: data/json/items/ammo/50.json @@ -48649,7 +48812,7 @@ msgstr "" #: data/json/items/ammo/500.json msgid ".500 S&W Magnum" msgid_plural ".500 S&W Magnums" -msgstr[0] "" +msgstr[0] ".500 S&W 馬格南彈" #. ~ Description for {'str': '.500 S&W Magnum'} #: data/json/items/ammo/500.json @@ -48662,12 +48825,12 @@ msgstr ".500 S&W 麥格農子彈使用 500 格令彈頭。這款子彈的威力 #: data/json/items/ammo/500.json msgid ".500 S&W Magnum, black powder" msgid_plural ".500 S&W Magnum, black powders" -msgstr[0] "" +msgstr[0] ".500 S&W 馬格南彈(黑火藥)" #: data/json/items/ammo/545x39.json msgid "5.45x39mm 7N10" msgid_plural "5.45x39mm 7N10s" -msgstr[0] "" +msgstr[0] "5.45x39mm 7N10 彈" #. ~ Description for {'str': '5.45x39mm 7N10'} #: data/json/items/ammo/545x39.json @@ -48683,7 +48846,7 @@ msgstr "" #: data/json/items/ammo/545x39.json msgid "5.45x39mm 7N22" msgid_plural "5.45x39mm 7N22s" -msgstr[0] "" +msgstr[0] "5.45x39mm 7N22 彈" #. ~ Description for {'str': '5.45x39mm 7N22'} #: data/json/items/ammo/545x39.json @@ -48695,7 +48858,7 @@ msgstr "5.45x39mm 7N22 子彈, 使用配以鋼頭的 57 格令穿甲彈頭。在 #: data/json/items/ammo/57.json msgid "5.7x28mm SS190" msgid_plural "5.7x28mm SS190s" -msgstr[0] "" +msgstr[0] "5.7x28mm SS190彈" #. ~ Description for {'str': '5.7x28mm SS190'} #: data/json/items/ammo/57.json @@ -48714,7 +48877,7 @@ msgstr "" #: data/json/items/ammo/57.json msgid "5.7x28mm, black powder" msgid_plural "5.7x28mm, black powders" -msgstr[0] "" +msgstr[0] "5.7x28mm 彈(黑火藥)" #. ~ Description for {'str': '5.7x28mm, black powder'} #. ~ Description for {'str': '5.7x28mm, reloaded'} @@ -48734,7 +48897,7 @@ msgstr "" #: data/json/items/ammo/5x50.json msgid "RA110 5x50mm flechette" msgid_plural "RA110 5x50mm flechettes" -msgstr[0] "" +msgstr[0] "RA110 5x50mm 鏢形彈" #. ~ Description for {'str': 'RA110 5x50mm flechette'} #: data/json/items/ammo/5x50.json @@ -48746,7 +48909,7 @@ msgstr "用來對付現代身體護甲的子彈, Rivtech 5x50mm 鋼鏢彈有著 #: data/json/items/ammo/5x50.json msgid "RA119 5x50mm penetrator" msgid_plural "RA119 5x50mm penetrators" -msgstr[0] "" +msgstr[0] "RA119 5x50mm 穿甲彈" #. ~ Description for {'str': 'RA119 5x50mm penetrator'} #: data/json/items/ammo/5x50.json @@ -48759,7 +48922,7 @@ msgstr "設計用來對付現代裝甲, Rivtech 5x50mm 鎢合金穿甲彈有著 #: data/json/items/ammo/66mm.json msgid "M74 rocket" msgid_plural "M74 rockets" -msgstr[0] "" +msgstr[0] "M74 火箭彈" #. ~ Description for {'str': 'M74 rocket'} #: data/json/items/ammo/66mm.json @@ -48772,7 +48935,7 @@ msgstr "66mm 的燃燒火箭, 被用於 M202 四聯裝火箭筒 。彈頭內裝 #: data/json/items/ammo/66mm.json msgid "66mm HEAT" msgid_plural "66mm HEATs" -msgstr[0] "" +msgstr[0] "66mm 高爆反坦克彈" #. ~ Description for 66mm HEAT #: data/json/items/ammo/66mm.json @@ -48786,7 +48949,7 @@ msgstr "" #: data/json/items/ammo/700nx.json msgid ".700 NX" msgid_plural ".700 NXs" -msgstr[0] "" +msgstr[0] ".700 NX 彈" #. ~ Description for {'str': '.700 NX'} #: data/json/items/ammo/700nx.json @@ -48802,7 +48965,7 @@ msgstr "" #: data/json/items/ammo/762.json msgid "7.62x39mm 57-N-231" msgid_plural "7.62x39mm 57-N-231s" -msgstr[0] "" +msgstr[0] "7.62x39mm 57-N-231 彈" #. ~ Description for {'str': '7.62x39mm 57-N-231'} #: data/json/items/ammo/762.json @@ -48818,7 +48981,7 @@ msgstr "" #: data/json/items/ammo/762.json msgid "7.62x39mm M67" msgid_plural "7.62x39mm M67s" -msgstr[0] "" +msgstr[0] "7.62x39mm M67 彈" #. ~ Description for {'str': '7.62x39mm M67'} #: data/json/items/ammo/762.json @@ -48834,7 +48997,7 @@ msgstr "" #: data/json/items/ammo/762R.json msgid "7.62x54mmR" msgid_plural "7.62x54mmRs" -msgstr[0] "" +msgstr[0] "7.62x54mmR 彈" #. ~ Description for {'str': '7.62x54mmR'} #: data/json/items/ammo/762R.json @@ -48851,7 +49014,7 @@ msgstr "" #: data/json/items/ammo/762x25.json msgid "7.62x25mm FMJ" msgid_plural "7.62x25mm FMJs" -msgstr[0] "" +msgstr[0] "7.62x25mm 被甲彈" #. ~ Description for {'str': '7.62x25mm FMJ'} #: data/json/items/ammo/762x25.json @@ -48864,7 +49027,7 @@ msgstr "蘇俄軍隊製作的 7.62x25mm 子彈的商業版本, 它是從 C96 手 #: data/json/items/ammo/762x25.json msgid "7.62x25mm JHP hot load" msgid_plural "7.62x25mm JHP hot loads" -msgstr[0] "" +msgstr[0] "7.62x25mm 空尖增壓彈" #. ~ Description for {'str': '7.62x25mm JHP hot load'} #: data/json/items/ammo/762x25.json @@ -48876,7 +49039,7 @@ msgstr "85格令的7.62x25mm 全金属被甲增压弹的民用版本。相比原 #: data/json/items/ammo/762x25.json msgid "7.62x25mm Type P" msgid_plural "7.62x25mm Type Ps" -msgstr[0] "" +msgstr[0] "7.62x25mm P型彈" #. ~ Description for {'str': '7.62x25mm Type P'} #: data/json/items/ammo/762x25.json @@ -48889,12 +49052,12 @@ msgstr "從 7.62x25mm 衍生出的亞音速彈藥, 專為無聲槍枝設計, 提 #: data/json/items/ammo/762x25.json msgid "7.62x25mm FMJ, black powder" msgid_plural "7.62x25mm FMJ, black powders" -msgstr[0] "" +msgstr[0] "7.62x25mm 被甲彈(黑火藥)" #: data/json/items/ammo/84x246mm.json msgid "84x246mm HE rocket" msgid_plural "84x246mm HE rockets" -msgstr[0] "" +msgstr[0] "84x246mm 高爆火箭彈" #. ~ Description for {'str': '84x246mm HE rocket'} #: data/json/items/ammo/84x246mm.json @@ -48906,7 +49069,7 @@ msgstr "一個卡爾古斯特 M3 無後座力砲所使用的 84x246mm 的高爆 #: data/json/items/ammo/84x246mm.json msgid "84x246mm HEDP rocket" msgid_plural "84x246mm HEDP rockets" -msgstr[0] "" +msgstr[0] "84x246mm 高爆兩用火箭彈" #. ~ Description for {'str': '84x246mm HEDP rocket'} #: data/json/items/ammo/84x246mm.json @@ -48919,7 +49082,7 @@ msgstr "一個卡爾古斯塔夫 M3 無後座力砲所使用的 84x246mm 的高 #: data/json/items/ammo/84x246mm.json msgid "84x246mm smoke rocket" msgid_plural "84x246mm smoke rockets" -msgstr[0] "" +msgstr[0] "84x246mm 煙霧火箭彈" #. ~ Description for {'str': '84x246mm smoke rocket'} #: data/json/items/ammo/84x246mm.json @@ -48930,16 +49093,52 @@ msgid "" msgstr "一個卡爾古斯塔夫 M3 無後座力砲所使用的 84x246mm 的煙霧標記彈。通常被用於發出信號、指定目標或者掩護步兵移動。" #: data/json/items/ammo/8x40mm.json -msgid "bootleg 8x40mm JHP" -msgid_plural "bootleg 8x40mm JHPs" -msgstr[0] "" +msgid "8x40mm JHP, handmade" +msgid_plural "8x40mm JHP, handmades" +msgstr[0] "8x40mm 空尖无壳弹(自制)" + +#. ~ Description for {'str': '8x40mm JHP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm JHP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "手工制造的仿制8x40mm 空尖无壳弹。由于是无壳弹,因此不能被拆解或是复装。" -#. ~ Description for {'str': 'bootleg 8x40mm JHP'} +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm caseless, handmade" +msgid_plural "8x40mm caseless, handmades" +msgstr[0] "8x40mm 无壳弹(自制)" + +#. ~ Description for {'str': '8x40mm caseless, handmade'} #: data/json/items/ammo/8x40mm.json msgid "" -"Bootleg duplicates of Rivtech 8x40mm caseless rounds. Being caseless " +"Handmade duplicates of Rivtech 8x40mm caseless rounds. Being caseless " "rounds, these cannot be disassembled or reloaded." -msgstr "Rivtech 8x40mm 口徑無殼彈的仿製品。作為無殼彈, 它不能夠被拆解或是重新組裝。" +msgstr "手工制造的仿制8x40mm 无壳弹。由于是无壳弹,因此不能被拆解或是复装。" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm HVP, handmade" +msgid_plural "8x40mm HVP, handmades" +msgstr[0] "8x40mm 高速穿甲无壳弹(自制)" + +#. ~ Description for {'str': '8x40mm HVP, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm HVP rounds. Being caseless rounds, " +"these cannot be disassembled or reloaded." +msgstr "手工制造的仿制8x40mm 高速穿甲无壳弹。由于是无壳弹,因此不能被拆解或是复装。" + +#: data/json/items/ammo/8x40mm.json +msgid "8x40mm tracer, handmade" +msgid_plural "8x40mm tracer, handmades" +msgstr[0] "8x40mm 曳光无壳弹(自制)" + +#. ~ Description for {'str': '8x40mm tracer, handmade'} +#: data/json/items/ammo/8x40mm.json +msgid "" +"Handmade duplicates of Rivtech 8x40mm tracer rounds. Being caseless rounds," +" these cannot be disassembled or reloaded." +msgstr "手工制造的仿制8x40mm 曳光无壳弹。由于是无壳弹,因此不能被拆解或是复装。" #. ~ Description for {'str_sp': '8x40mm caseless'} #: data/json/items/ammo/8x40mm.json @@ -48951,7 +49150,7 @@ msgstr "8x40mm 口徑的無彈殼子彈, 適用於 Rivtech 公司的槍械。作 #: data/json/items/ammo/8x40mm.json msgid "8x40mm sporting" msgid_plural "8x40mm sportings" -msgstr[0] "" +msgstr[0] "8x40mm 比賽無殼彈" #. ~ Description for {'str': '8x40mm sporting'} #: data/json/items/ammo/8x40mm.json @@ -48964,7 +49163,7 @@ msgstr "8x40mm 口徑的輕量無彈殼競賽用子彈, 適用於 Rivtech 公司 #: data/json/items/ammo/8x40mm.json msgid "8x40mm HVP" msgid_plural "8x40mm HVPs" -msgstr[0] "" +msgstr[0] "8x40mm 高速穿甲無殼彈" #. ~ Description for {'str': '8x40mm HVP'} #: data/json/items/ammo/8x40mm.json @@ -48978,7 +49177,7 @@ msgstr "8x40mm 無殼彈, 高速穿甲型子彈。先進的軍用彈, 貧化鈾 #: data/json/items/ammo/8x40mm.json msgid "8x40mm tracer" msgid_plural "8x40mm tracers" -msgstr[0] "" +msgstr[0] "8x40mm 曳光無殼彈" #. ~ Description for {'str': '8x40mm tracer'} #: data/json/items/ammo/8x40mm.json @@ -48994,7 +49193,7 @@ msgstr "" #: data/json/items/ammo/8x40mm.json msgid "8x40mm JHP" msgid_plural "8x40mm JHPs" -msgstr[0] "" +msgstr[0] "8x40mm 空尖無殼彈" #. ~ Description for {'str': '8x40mm JHP'} #: data/json/items/ammo/8x40mm.json @@ -49007,7 +49206,7 @@ msgstr "8x40mm 口徑的無殼空尖彈, 適用於 Rivtech 公司的軍規槍械 #: data/json/items/ammo/9mm.json msgid "9x19mm JHP" msgid_plural "9x19mm JHPs" -msgstr[0] "" +msgstr[0] "9x19mm 空尖彈" #. ~ Description for {'str': '9x19mm JHP'} #: data/json/items/ammo/9mm.json @@ -49023,7 +49222,7 @@ msgstr "" #: data/json/items/ammo/9mm.json msgid "9x19mm FMJ" msgid_plural "9x19mm FMJs" -msgstr[0] "" +msgstr[0] "9x19mm 被甲彈" #. ~ Description for {'str': '9x19mm FMJ'} #: data/json/items/ammo/9mm.json @@ -49036,7 +49235,7 @@ msgstr "9x19mm 子彈使用以黃銅包覆的 115 克令彈頭。即使生產了 #: data/json/items/ammo/9mm.json msgid "9x19mm +P" msgid_plural "9x19mm +Ps" -msgstr[0] "" +msgstr[0] "9x19mm +P 彈" #. ~ Description for {'str': '9x19mm +P'} #: data/json/items/ammo/9mm.json @@ -49048,7 +49247,7 @@ msgstr "高壓的 9x19mm 子彈, 較高的彈速使得它具有更高的準繩 #: data/json/items/ammo/9mm.json msgid "9x19mm +P+" msgid_plural "9x19mm +P+s" -msgstr[0] "" +msgstr[0] "9x19mm +P+ 彈" #. ~ Description for {'str': '9x19mm +P+'} #: data/json/items/ammo/9mm.json @@ -49060,17 +49259,17 @@ msgstr "比 9mm 高壓彈更進一步, 這款超高壓彈具有更強的破壞 #: data/json/items/ammo/9mm.json msgid "9x19mm JHP, black powder" msgid_plural "9x19mm JHP, black powders" -msgstr[0] "" +msgstr[0] "9x19mm 空尖彈(黑火藥)" #: data/json/items/ammo/9mm.json msgid "9x19mm FMJ, black powder" msgid_plural "9x19mm FMJ, black powders" -msgstr[0] "" +msgstr[0] "9x19mm 被甲彈(黑火藥)" #: data/json/items/ammo/9x18.json msgid "9x18mm 57-N-181S" msgid_plural "9x18mm 57-N-181Ss" -msgstr[0] "" +msgstr[0] "9x18mm 57-N-181S 彈" #. ~ Description for {'str': '9x18mm 57-N-181S'} #: data/json/items/ammo/9x18.json @@ -49085,7 +49284,7 @@ msgstr "" #: data/json/items/ammo/9x18.json msgid "9x18mm SP-7" msgid_plural "9x18mm SP-7s" -msgstr[0] "" +msgstr[0] "9x18mm SP-7 彈" #. ~ Description for {'str': '9x18mm SP-7'} #: data/json/items/ammo/9x18.json @@ -49098,7 +49297,7 @@ msgstr "9x18mm 馬卡洛夫 SP-7 子彈。9x18mm 子彈在 20 世紀的東歐相 #: data/json/items/ammo/9x18.json msgid "9x18mm RG028" msgid_plural "9x18mm RG028s" -msgstr[0] "" +msgstr[0] "9x18mm RG028 彈" #. ~ Description for {'str': '9x18mm RG028'} #: data/json/items/ammo/9x18.json @@ -49110,17 +49309,17 @@ msgstr "9x18mm 馬卡洛夫 RG028 子彈, 彈頭使用加硬的鋼蕊以提升 #: data/json/items/ammo/9x18.json msgid "9x18mm, black powder" msgid_plural "9x18mm, black powders" -msgstr[0] "" +msgstr[0] "9x18mm 彈(黑火藥)" #: data/json/items/ammo/9x18.json msgid "9x18mm FMJ, black powder" msgid_plural "9x18mm FMJ, black powders" -msgstr[0] "" +msgstr[0] "9x18mm 被甲彈(黑火藥)" #: data/json/items/ammo/atgm.json msgid "152mm ATGM HEAT" msgid_plural "152mm ATGM HEATs" -msgstr[0] "" +msgstr[0] "152mm 熱能追踪反坦克導彈" #. ~ Description for {'str': '152mm ATGM HEAT'} #: data/json/items/ammo/atgm.json @@ -49132,7 +49331,7 @@ msgstr "一件由发射管发射,具有光学制导的热能追踪的导弹。 #: data/json/items/ammo/barb.json msgid "paralyzing barb" msgid_plural "paralyzing barbs" -msgstr[0] "" +msgstr[0] "麻痺毒刺" #. ~ Description for {'str': 'paralyzing barb'} #: data/json/items/ammo/barb.json @@ -49144,7 +49343,7 @@ msgstr "微小的毒液滴從這個鋒利的倒鉤的海綿狀組織中滴出。 #: data/json/items/ammo/chemical_spray.json msgid "sprayable toxic gas" msgid_plural "sprayable toxic gas" -msgstr[0] "" +msgstr[0] "噴霧式毒氣劑" #. ~ Description for {'str_sp': 'sprayable toxic gas'} #: data/json/items/ammo/chemical_spray.json @@ -49156,7 +49355,7 @@ msgstr "混合了家用清潔劑, 使用在噴射器上的噴灑劑。最好給 #: data/json/items/ammo/chemical_spray.json msgid "sprayable fungicide" msgid_plural "sprayable fungicide" -msgstr[0] "" +msgstr[0] "噴霧式抗真菌劑" #. ~ Description for {'str_sp': 'sprayable fungicide'} #: data/json/items/ammo/chemical_spray.json @@ -49168,7 +49367,7 @@ msgstr "混合了滅蕈藥, 使用在噴射器上的噴灑劑。最好給那些 #: data/json/items/ammo/chemical_spray.json msgid "sprayable insecticide" msgid_plural "sprayable insecticide" -msgstr[0] "" +msgstr[0] "噴霧式殺蟲劑" #. ~ Description for {'str_sp': 'sprayable insecticide'} #: data/json/items/ammo/chemical_spray.json @@ -49188,7 +49387,7 @@ msgstr "一個內含黑火藥和金屬彈丸的紙卷彈藥。能夠加快老式 #: data/mods/Generic_Guns/ammo/obsolete.json msgid "paper shot cartridge" msgid_plural "paper shot cartridges" -msgstr[0] "" +msgstr[0] "紙卷霰彈" #. ~ Description for {'str': 'paper shot cartridge'} #: data/json/items/ammo/flintlock.json @@ -49201,7 +49400,7 @@ msgstr "一個內含黑火藥和金屬彈丸的紙卷彈藥。能夠加快老式 #: data/json/items/ammo/metal_rail.json msgid "rebar rail" msgid_plural "rebar rails" -msgstr[0] "" +msgstr[0] "鋼筋磁軌彈" #. ~ Description for {'str': 'rebar rail'} #: data/json/items/ammo/metal_rail.json @@ -49214,7 +49413,7 @@ msgstr "一小段被拉直的鐵磁螺紋鋼筋, 末端被磨尖了。能夠利 #: data/json/items/ammo/metal_rail.json msgid "steel rail" msgid_plural "steel rails" -msgstr[0] "" +msgstr[0] "鋼條磁軌彈" #. ~ Description for {'str': 'steel rail'} #: data/json/items/ammo/metal_rail.json @@ -49227,7 +49426,7 @@ msgstr "一小段被鍛造過的堅硬鋼筋, 末端被磨尖了。能夠利用 #: data/json/items/ammo/nail.json msgid "flechette" msgid_plural "flechettes" -msgstr[0] "" +msgstr[0] "鋼鏢" #. ~ Description for {'str': 'flechette'} #: data/json/items/ammo/nail.json @@ -49239,7 +49438,7 @@ msgstr "一根微小的鋼飛鏢。可從釘槍或類似的武器發射, 也可 #: data/json/items/ammo/nail.json msgid "nail" msgid_plural "nails" -msgstr[0] "" +msgstr[0] "鐵釘" #. ~ Description for {'str': 'nail'} #: data/json/items/ammo/nail.json @@ -49254,41 +49453,41 @@ msgid "A tube of small paintballs. They deal virtually no damage." msgstr "一管小漆彈。幾乎沒有殺傷力。" #: data/json/items/ammo/rpg.json -msgid "PG-7VL 93mm rocket" -msgid_plural "PG-7VL 93mm rockets" -msgstr[0] "" +msgid "PG-7VL RPG-7 rocket" +msgid_plural "PG-7VL RPG-7 rockets" +msgstr[0] "PG-7VL RPG-7 火箭弹" -#. ~ Description for PG-7VL 93mm rocket +#. ~ Description for PG-7VL RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "93mm single-stage high-explosive ammunition for the RPG-7." msgstr "供 RPG-7 使用的 93mm 口徑高爆彈藥。" #: data/json/items/ammo/rpg.json -msgid "PG-7VR 64mm/105mm rocket" -msgid_plural "PG-7VR 64mm/105mm rockets" -msgstr[0] "" +msgid "PG-7VR RPG-7 rocket" +msgid_plural "PG-7VR RPG-7 rockets" +msgstr[0] "PG-7VR RPG-7 火箭弹" -#. ~ Description for PG-7VR 64mm/105mm rocket +#. ~ Description for PG-7VR RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "64mm/105mm high-explosive tandem ammunition for the RPG-7." msgstr "用於 RPG-7 的 64mm/105mm 高爆串聯彈藥。" #: data/json/items/ammo/rpg.json -msgid "TBG-7V 105mm rocket" -msgid_plural "TBG-7V 105mm rockets" -msgstr[0] "" +msgid "TBG-7V RPG-7 rocket" +msgid_plural "TBG-7V RPG-7 rockets" +msgstr[0] "TBG-7V RPG-7 火箭弹" -#. ~ Description for TBG-7V 105mm rocket +#. ~ Description for TBG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "105mm thermobaric ammunition for the RPG-7." msgstr "用於 RPG-7 的 105mm 熱壓式彈藥。" #: data/json/items/ammo/rpg.json -msgid "OG-7V 40mm rocket" -msgid_plural "OG-7V 40mm rockets" -msgstr[0] "" +msgid "OG-7V RPG-7 rocket" +msgid_plural "OG-7V RPG-7 rockets" +msgstr[0] "OG-7V RPG-7 火箭弹" -#. ~ Description for OG-7V 40mm rocket +#. ~ Description for OG-7V RPG-7 rocket #: data/json/items/ammo/rpg.json msgid "" "40mm high-explosive fragmentation antipersonnel ammunition for the RPG-7." @@ -49297,32 +49496,32 @@ msgstr "用於 RPG-7 的 40mm 高爆破片反人員彈藥。" #: data/json/items/ammo/shot.json msgid "birdshot, black powder" msgid_plural "birdshot, black powders" -msgstr[0] "" +msgstr[0] "獵鳥彈(黑火藥)" #: data/json/items/ammo/shot.json msgid "dragon's breath shell, black powder" msgid_plural "dragon's breath shell, black powders" -msgstr[0] "" +msgstr[0] "龍息霰彈(黑火藥)" #: data/json/items/ammo/shot.json msgid "00 shot, black powder" msgid_plural "00 shot, black powders" -msgstr[0] "" +msgstr[0] "獵鹿彈(黑火藥)" #: data/json/items/ammo/shot.json msgid "flechette shell, black powder" msgid_plural "flechette shell, black powders" -msgstr[0] "" +msgstr[0] "鏢形霰彈(黑火藥)" #: data/json/items/ammo/shot.json msgid "shotgun slug, black powder" msgid_plural "shotgun slug, black powders" -msgstr[0] "" +msgstr[0] "獨頭霰彈(黑火藥)" #: data/json/items/ammo/shot.json msgid "00 shot" msgid_plural "00 shots" -msgstr[0] "" +msgstr[0] "獵鹿彈" #. ~ Description for {'str': '00 shot'} #. ~ Description for {'str_sp': 'shotshell, buckshot'} @@ -49335,7 +49534,7 @@ msgstr "子彈內裝滿了金屬小圓球。威力超群, 彈著點密集, 因 #: data/json/items/ammo/shot.json msgid "shotgun beanbag" msgid_plural "shotgun beanbags" -msgstr[0] "" +msgstr[0] "沙包彈" #. ~ Description for {'str': 'shotgun beanbag'} #. ~ Description for {'str_sp': 'shotshell, beanbag'} @@ -49346,7 +49545,7 @@ msgstr "一個霰彈槍用的豆袋子彈, 用於非致命的癱瘓用途。" #: data/json/items/ammo/shot.json msgid "birdshot" msgid_plural "birdshots" -msgstr[0] "" +msgstr[0] "獵鳥彈" #. ~ Description for {'str': 'birdshot'} #: data/json/items/ammo/shot.json @@ -49358,7 +49557,7 @@ msgstr "威力有限的霰彈槍彈藥。設計用來打鳥以及進行一些小 #: data/json/items/ammo/shot.json msgid "dragon's breath shell" msgid_plural "dragon's breath shells" -msgstr[0] "" +msgstr[0] "龍息霰彈" #. ~ Description for {'str': "dragon's breath shell"} #: data/json/items/ammo/shot.json @@ -49372,7 +49571,7 @@ msgstr "填充镁颗粒或碎片的霰弹枪弹,主要用作紧急求救信号 #: data/json/items/ammo/shot.json msgid "flechette shell" msgid_plural "flechette shells" -msgstr[0] "" +msgstr[0] "鏢形霰彈" #. ~ Description for {'str': 'flechette shell'} #: data/json/items/ammo/shot.json @@ -49385,7 +49584,7 @@ msgstr "填入了許多小鋼鏢的霰彈。威力極強, 在近距離有非常 #: data/json/items/ammo/shot.json msgid "explosive slug" msgid_plural "explosive slugs" -msgstr[0] "" +msgstr[0] "高爆霰彈" #. ~ Description for {'str': 'explosive slug'} #: data/json/items/ammo/shot.json @@ -49397,7 +49596,7 @@ msgstr "造成小型爆炸的霰彈, 高破壞力, 但是相對短程與低命 #: data/json/items/ammo/shot.json msgid "00 shot, scrap loaded" msgid_plural "00 shot, scrap loadeds" -msgstr[0] "" +msgstr[0] "獵鹿彈(廢料)" #. ~ Description for {'str': '00 shot, scrap loaded'} #. ~ Description for {'str_sp': 'shotshell, junk'} @@ -49411,12 +49610,12 @@ msgstr "一個霰彈殼用雜七雜八的東西當裝填物。比獵鳥霰彈強 #: data/json/items/ammo/shot.json msgid "00 shot, black powder, scrap loaded" msgid_plural "00 shot, black powder, scrap loadeds" -msgstr[0] "" +msgstr[0] "獵鹿彈(廢料黑火藥)" #: data/json/items/ammo/shot.json msgid "shotgun slug" msgid_plural "shotgun slugs" -msgstr[0] "" +msgstr[0] "獨頭彈" #. ~ Description for {'str': 'shotgun slug'} #: data/json/items/ammo/shot.json @@ -49428,7 +49627,7 @@ msgstr "單顆全金屬彈頭的設計能讓霰彈槍擊中較遠的目標, 能 #: data/json/items/ammo/shotpaper.json msgid "birdshot paper cartridge" msgid_plural "birdshot paper cartridges" -msgstr[0] "" +msgstr[0] "紙卷獵鳥彈" #. ~ Description for {'str': 'birdshot paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -49440,7 +49639,7 @@ msgstr "一颗纸卷弹,里面填充有预先称量好的黑火药和等量的 #: data/json/items/ammo/shotpaper.json msgid "pyrotechnic paper cartridge" msgid_plural "pyrotechnic paper cartridges" -msgstr[0] "" +msgstr[0] "紙卷燃燒彈" #. ~ Description for {'str': 'pyrotechnic paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -49453,7 +49652,7 @@ msgstr "一颗纸卷弹,里面填充有预先称量好的黑火药和等量的 #: data/json/items/ammo/shotpaper.json msgid "buckshot paper cartridge" msgid_plural "buckshot paper cartridges" -msgstr[0] "" +msgstr[0] "紙卷獵鹿彈" #. ~ Description for {'str': 'buckshot paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -49465,7 +49664,7 @@ msgstr "一颗纸卷弹,里面填充有预先称量好的黑火药和等量的 #: data/json/items/ammo/shotpaper.json msgid ".62 paper cartridge" msgid_plural ".62 paper cartridges" -msgstr[0] "" +msgstr[0] ".62 紙卷彈" #. ~ Description for {'str': '.62 paper cartridge'} #: data/json/items/ammo/shotpaper.json @@ -49484,7 +49683,7 @@ msgstr "一個沈重的塑膠信號彈殼。似乎被改造成霰彈槍殼了。 #: data/json/items/ammo/weldgas.json msgid "oxyacetylene" msgid_plural "oxyacetylenes" -msgstr[0] "" +msgstr[0] "氧乙炔" #. ~ Description for {'str': 'oxyacetylene'} #: data/json/items/ammo/weldgas.json @@ -49799,7 +49998,7 @@ msgstr "" #: data/json/items/armor/ammo_pouch.json msgid "XL Kevlar vest" msgid_plural "XL Kevlar vests" -msgstr[0] "" +msgstr[0] "XL 防彈背心" #. ~ Description for {'str': 'XL Kevlar vest'} #: data/json/items/armor/ammo_pouch.json @@ -49985,7 +50184,7 @@ msgstr "一個用頂級工藝打造的輕量、靈活的防彈背心。裡面安 #: data/json/items/armor/ballistic_armor.json msgid "lamellar Kevlar vest" msgid_plural "lamellar Kevlar vests" -msgstr[0] "" +msgstr[0] "層片防彈背心" #. ~ Description for {'str': 'lamellar Kevlar vest'} #: data/json/items/armor/ballistic_armor.json @@ -50089,7 +50288,7 @@ msgstr "一個儲存榴彈的小袋子, 袋子上的皮帶可以繫到你的腰 #: data/json/items/armor/bandolier.json msgid "stone pouch" msgid_plural "stone pouches" -msgstr[0] "" +msgstr[0] "石子袋" #. ~ Description for {'str': 'stone pouch', 'str_pl': 'stone pouches'} #: data/json/items/armor/bandolier.json @@ -50329,7 +50528,7 @@ msgstr "带有口袋,腰带环和刀套的工具腰带,最多能够收纳六 #: data/json/items/armor/belts.json msgid "webbing belt" msgid_plural "webbing belts" -msgstr[0] "" +msgstr[0] "編織腰帶" #. ~ Description for {'str': 'webbing belt'} #: data/json/items/armor/belts.json @@ -50362,7 +50561,7 @@ msgstr "強韌的皮革靴子。非常耐用。" #: data/json/items/armor/boots.json msgid "pair of occult boots" msgid_plural "pairs of occult boots" -msgstr[0] "" +msgstr[0] "邪異之靴" #. ~ Description for {'str': 'pair of occult boots', 'str_pl': 'pairs of #. occult boots'} @@ -50715,7 +50914,7 @@ msgstr "簡單的拖鞋。但是不適合跑步。" #: data/json/items/armor/boots.json msgid "pair of expensive flip-flops" msgid_plural "pairs of flip-flops" -msgstr[0] "" +msgstr[0] "人字拖" #. ~ Description for {'str': 'pair of expensive flip-flops', 'str_pl': 'pairs #. of flip-flops'} @@ -51015,7 +51214,7 @@ msgstr "一雙自帶輪子的運動鞋,目前輪子已經彈出可以滑行。 #: data/json/items/armor/boots.json msgid "pair of chainmail chausses" msgid_plural "pairs of chainmail chausses" -msgstr[0] "" +msgstr[0] "鎖環鐙靴" #. ~ Description for {'str': 'pair of chainmail chausses', 'str_pl': 'pairs of #. chainmail chausses'} @@ -51063,7 +51262,7 @@ msgstr "襪子。穿在腳上的玩意。" #: data/json/items/armor/boots.json msgid "pair of ankle socks" msgid_plural "pairs of ankle socks" -msgstr[0] "" +msgstr[0] "護踝襪" #. ~ Description for {'str': 'pair of ankle socks', 'str_pl': 'pairs of ankle #. socks'} @@ -51255,7 +51454,7 @@ msgstr "一件嵌入了攝影機與 LED 的塑膠斗篷, 穿戴並啟動後能 #: data/json/items/armor/cloaks.json msgid "FB51 optical cloak (on)" msgid_plural "FB51 optical cloaks (on)" -msgstr[0] "" +msgstr[0] "FB51 光學迷彩斗篷(開)" #. ~ Use action msg for {'str': 'FB51 optical cloak (on)', 'str_pl': 'FB51 #. optical cloaks (on)'}. @@ -51469,7 +51668,7 @@ msgstr "一种可以穿在和服外面的飘逸的衣服。" #: data/json/items/armor/coats.json msgid "bathrobe" msgid_plural "bathrobes" -msgstr[0] "" +msgstr[0] "浴袍" #. ~ Description for {'str': 'bathrobe'} #: data/json/items/armor/coats.json @@ -52175,7 +52374,7 @@ msgstr "一副重達 8 盎司的紅色大拳套。戴著它幾乎沒辦法作靈 #: data/json/items/armor/gloves.json msgid "pair of chainmail gloves" msgid_plural "pairs of chainmail gloves" -msgstr[0] "" +msgstr[0] "鏈甲手套" #. ~ Description for {'str': 'pair of chainmail gloves', 'str_pl': 'pairs of #. chainmail gloves'} @@ -52227,7 +52426,7 @@ msgstr "由酸液螞蟻的生物矽化外骨骼, 精心清洗並剪裁製成的 #: data/json/items/armor/gloves.json msgid "fencing gauntlet" msgid_plural "fencing gauntlets" -msgstr[0] "" +msgstr[0] "擊劍護手" #. ~ Description for {'str': 'fencing gauntlet'} #: data/json/items/armor/gloves.json @@ -52239,7 +52438,7 @@ msgstr "一只单面绒面手套,有着结实的棉制手腕,带衬垫的手 #: data/json/items/armor/gloves.json msgid "fencing gauntlet (left)" msgid_plural "fencing gauntlets (left)" -msgstr[0] "" +msgstr[0] "擊劍護手(左)" #. ~ Description for {'str': 'fencing gauntlet (left)', 'str_pl': 'fencing #. gauntlets (left)'} @@ -52408,7 +52607,7 @@ msgstr "一雙訂製的手套, 由凱夫勒裝甲與棉布製成。便於穿戴, #: data/json/items/armor/gloves.json msgid "pair of fingerless survivor gloves" msgid_plural "pairs of fingerless survivor gloves" -msgstr[0] "" +msgstr[0] "無指幸存者手套" #. ~ Description for {'str': 'pair of fingerless survivor gloves', 'str_pl': #. 'pairs of fingerless survivor gloves'} @@ -52750,7 +52949,7 @@ msgstr "無論是狩獵、修理牧場、或只是幻想你有匹馬, 這頂帽 #: data/json/items/armor/hats.json msgid "drinking hat" msgid_plural "drinking hats" -msgstr[0] "" +msgstr[0] "飲水帽" #. ~ Description for {'str': 'drinking hat'} #: data/json/items/armor/hats.json @@ -53244,7 +53443,7 @@ msgstr "一頂厚實的皮革頭盔, 能提供絕佳的頭部防護。" #: data/json/items/armor/helmets.json msgid "large wolf skull" msgid_plural "large wolf skulls" -msgstr[0] "" +msgstr[0] "大型狼頭骨" #. ~ Description for {'str': 'large wolf skull'} #: data/json/items/armor/helmets.json @@ -53317,7 +53516,7 @@ msgstr "一種粗製的保護罩, 可保護眼睛免受雨水和陽光的傷害, #: data/json/items/armor/helmets.json msgid "great helm" msgid_plural "great helmets" -msgstr[0] "" +msgstr[0] "巨盔" #. ~ Description for {'str': 'great helm', 'str_pl': 'great helmets'} #: data/json/items/armor/helmets.json @@ -53730,7 +53929,7 @@ msgstr "一顆鑲嵌了假鑽的牙齒, 能套在牙齒上。意外的適合, #: data/json/items/armor/jewelry.json msgid "garnet dental grill" msgid_plural "garnet dental grills" -msgstr[0] "" +msgstr[0] "石榴石假牙" #. ~ Description for {'str': 'garnet dental grill'} #: data/json/items/armor/jewelry.json @@ -53741,7 +53940,7 @@ msgstr "一颗石榴石假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "amethyst dental grill" msgid_plural "amethyst dental grills" -msgstr[0] "" +msgstr[0] "紫水晶假牙" #. ~ Description for {'str': 'amethyst dental grill'} #: data/json/items/armor/jewelry.json @@ -53752,7 +53951,7 @@ msgstr "一颗紫水晶假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "aquamarine dental grill" msgid_plural "aquamarine dental grills" -msgstr[0] "" +msgstr[0] "海藍寶石假牙" #. ~ Description for {'str': 'aquamarine dental grill'} #: data/json/items/armor/jewelry.json @@ -53764,7 +53963,7 @@ msgstr "一颗海蓝宝石假牙,套在牙齿上。看上去异常的闪亮耀 #: data/json/items/armor/jewelry.json msgid "emerald dental grill" msgid_plural "emerald dental grills" -msgstr[0] "" +msgstr[0] "祖母綠假牙" #. ~ Description for {'str': 'emerald dental grill'} #: data/json/items/armor/jewelry.json @@ -53775,7 +53974,7 @@ msgstr "一颗祖母绿假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "alexandrite dental grill" msgid_plural "alexandrite dental grills" -msgstr[0] "" +msgstr[0] "紫翠玉假牙" #. ~ Description for {'str': 'alexandrite dental grill'} #: data/json/items/armor/jewelry.json @@ -53787,7 +53986,7 @@ msgstr "一颗紫翠玉假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "ruby dental grill" msgid_plural "ruby dental grills" -msgstr[0] "" +msgstr[0] "紅寶石假牙" #. ~ Description for {'str': 'ruby dental grill'} #: data/json/items/armor/jewelry.json @@ -53798,7 +53997,7 @@ msgstr "一颗红宝石假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "peridot dental grill" msgid_plural "peridot dental grills" -msgstr[0] "" +msgstr[0] "橄欖石假牙" #. ~ Description for {'str': 'peridot dental grill'} #: data/json/items/armor/jewelry.json @@ -53809,7 +54008,7 @@ msgstr "一颗橄榄石假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "sapphire dental grill" msgid_plural "sapphire dental grills" -msgstr[0] "" +msgstr[0] "藍寶石假牙" #. ~ Description for {'str': 'sapphire dental grill'} #: data/json/items/armor/jewelry.json @@ -53820,7 +54019,7 @@ msgstr "一颗蓝宝石假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "tourmaline dental grill" msgid_plural "tourmaline dental grills" -msgstr[0] "" +msgstr[0] "電氣石假牙" #. ~ Description for {'str': 'tourmaline dental grill'} #: data/json/items/armor/jewelry.json @@ -53832,7 +54031,7 @@ msgstr "一颗电气石假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "citrine dental grill" msgid_plural "citrine dental grills" -msgstr[0] "" +msgstr[0] "黃水晶假牙" #. ~ Description for {'str': 'citrine dental grill'} #: data/json/items/armor/jewelry.json @@ -53853,7 +54052,7 @@ msgstr "一個有很多裝飾的髮夾。" #: data/json/items/armor/jewelry.json msgid "blue topaz dental grill" msgid_plural "blue topaz dental grills" -msgstr[0] "" +msgstr[0] "藍黃玉假牙" #. ~ Description for {'str': 'blue topaz dental grill'} #: data/json/items/armor/jewelry.json @@ -53865,7 +54064,7 @@ msgstr "一颗蓝黄玉假牙,套在牙齿上。看上去异常的闪亮耀眼 #: data/json/items/armor/jewelry.json msgid "diamond and gold ring" msgid_plural "diamond and gold rings" -msgstr[0] "" +msgstr[0] "鑽石金戒指" #. ~ Description for {'str': 'diamond and gold ring'} #: data/json/items/armor/jewelry.json @@ -53977,7 +54176,7 @@ msgstr "一個普通的銅戒指。不是很閃亮,也不是很受歡迎。如 #: data/json/items/armor/jewelry.json msgid "pair of cufflinks" msgid_plural "pairs of cufflinks" -msgstr[0] "" +msgstr[0] "袖扣" #. ~ Description for {'str': 'pair of cufflinks', 'str_pl': 'pairs of #. cufflinks'} @@ -53991,7 +54190,7 @@ msgstr "一對無標記的銀色袖扣。袖扣用於固定禮服襯衫的袖口 #: data/json/items/armor/jewelry.json msgid "pair of intricate cufflinks" msgid_plural "pairs of intricate cufflinks" -msgstr[0] "" +msgstr[0] "精美袖扣" #. ~ Description for {'str': 'pair of intricate cufflinks', 'str_pl': 'pairs #. of intricate cufflinks'} @@ -54005,7 +54204,7 @@ msgstr "一對昂貴的銀色袖扣,採用金色齒輪和碎形圖案的精細 #: data/json/items/armor/jewelry.json msgid "garnet and gold cufflinks" msgid_plural "garnet and gold cufflinks" -msgstr[0] "" +msgstr[0] "石榴石金袖扣" #. ~ Description for {'str_sp': 'garnet and gold cufflinks'} #. ~ Description for {'str_sp': 'garnet and silver cufflinks'} @@ -54017,7 +54216,7 @@ msgstr "镶嵌石榴石的袖扣。" #: data/json/items/armor/jewelry.json msgid "diamond and gold cufflinks" msgid_plural "diamond and gold cufflinks" -msgstr[0] "" +msgstr[0] "鑽石金袖扣" #. ~ Description for {'str_sp': 'diamond and gold cufflinks'} #. ~ Description for {'str_sp': 'diamond and silver cufflinks'} @@ -54029,7 +54228,7 @@ msgstr "镶嵌钻石的袖扣。" #: data/json/items/armor/jewelry.json msgid "amethyst and gold cufflinks" msgid_plural "amethyst and gold cufflinks" -msgstr[0] "" +msgstr[0] "紫水晶金袖扣" #. ~ Description for {'str_sp': 'amethyst and gold cufflinks'} #. ~ Description for {'str_sp': 'amethyst and silver cufflinks'} @@ -54041,7 +54240,7 @@ msgstr "镶嵌紫水晶的袖扣。" #: data/json/items/armor/jewelry.json msgid "aquamarine and gold cufflinks" msgid_plural "aquamarine and gold cufflinks" -msgstr[0] "" +msgstr[0] "海藍寶石金袖扣" #. ~ Description for {'str_sp': 'aquamarine and gold cufflinks'} #. ~ Description for {'str_sp': 'aquamarine and silver cufflinks'} @@ -54053,7 +54252,7 @@ msgstr "镶嵌海蓝宝石的袖扣。" #: data/json/items/armor/jewelry.json msgid "emerald and gold cufflinks" msgid_plural "emerald and gold cufflinks" -msgstr[0] "" +msgstr[0] "祖母綠金袖扣" #. ~ Description for {'str_sp': 'emerald and gold cufflinks'} #. ~ Description for {'str_sp': 'emerald and silver cufflinks'} @@ -54065,7 +54264,7 @@ msgstr "镶嵌祖母绿的袖扣。" #: data/json/items/armor/jewelry.json msgid "alexandrite and gold cufflinks" msgid_plural "alexandrite and gold cufflinks" -msgstr[0] "" +msgstr[0] "紫翠玉金袖扣" #. ~ Description for {'str_sp': 'alexandrite and gold cufflinks'} #. ~ Description for {'str_sp': 'alexandrite and silver cufflinks'} @@ -54077,7 +54276,7 @@ msgstr "镶嵌紫翠玉的袖扣。" #: data/json/items/armor/jewelry.json msgid "ruby and gold cufflinks" msgid_plural "ruby and gold cufflinks" -msgstr[0] "" +msgstr[0] "紅寶石金袖扣" #. ~ Description for {'str_sp': 'ruby and gold cufflinks'} #. ~ Description for {'str_sp': 'ruby and silver cufflinks'} @@ -54089,7 +54288,7 @@ msgstr "镶嵌红宝石的袖扣。" #: data/json/items/armor/jewelry.json msgid "peridot and gold cufflinks" msgid_plural "peridot and gold cufflinks" -msgstr[0] "" +msgstr[0] "橄欖石金袖扣" #. ~ Description for {'str_sp': 'peridot and gold cufflinks'} #. ~ Description for {'str_sp': 'peridot and silver cufflinks'} @@ -54101,7 +54300,7 @@ msgstr "镶嵌橄榄石的袖扣。" #: data/json/items/armor/jewelry.json msgid "sapphire and gold cufflinks" msgid_plural "sapphire and gold cufflinks" -msgstr[0] "" +msgstr[0] "藍寶石金袖扣" #. ~ Description for {'str_sp': 'sapphire and gold cufflinks'} #. ~ Description for {'str_sp': 'sapphire and silver cufflinks'} @@ -54113,7 +54312,7 @@ msgstr "镶嵌蓝宝石的袖扣。" #: data/json/items/armor/jewelry.json msgid "tourmaline and gold cufflinks" msgid_plural "tourmaline and gold cufflinks" -msgstr[0] "" +msgstr[0] "電氣石金袖扣" #. ~ Description for {'str_sp': 'tourmaline and gold cufflinks'} #. ~ Description for {'str_sp': 'tourmaline and silver cufflinks'} @@ -54125,7 +54324,7 @@ msgstr "镶嵌电气石的袖扣。" #: data/json/items/armor/jewelry.json msgid "citrine and gold cufflinks" msgid_plural "citrine and gold cufflinks" -msgstr[0] "" +msgstr[0] "黃水晶金袖扣" #. ~ Description for {'str_sp': 'citrine and gold cufflinks'} #. ~ Description for {'str_sp': 'citrine and silver cufflinks'} @@ -54137,7 +54336,7 @@ msgstr "镶嵌黄水晶的袖扣。" #: data/json/items/armor/jewelry.json msgid "blue topaz and gold cufflinks" msgid_plural "blue topaz and gold cufflinks" -msgstr[0] "" +msgstr[0] "藍黃玉金袖扣" #. ~ Description for {'str_sp': 'blue topaz and gold cufflinks'} #. ~ Description for {'str_sp': 'blue topaz and silver cufflinks'} @@ -54149,7 +54348,7 @@ msgstr "镶嵌蓝黄玉的袖扣。" #: data/json/items/armor/jewelry.json msgid "opal and gold cufflinks" msgid_plural "opal and gold cufflinks" -msgstr[0] "" +msgstr[0] "蛋白石金袖扣" #. ~ Description for {'str_sp': 'opal and gold cufflinks'} #. ~ Description for {'str_sp': 'opal and silver cufflinks'} @@ -54161,7 +54360,7 @@ msgstr "镶嵌蛋白石的袖扣。" #: data/json/items/armor/jewelry.json msgid "pearl and gold cufflinks" msgid_plural "pearl and gold cufflinks" -msgstr[0] "" +msgstr[0] "珍珠金袖扣" #. ~ Description for {'str_sp': 'pearl and gold cufflinks'} #. ~ Description for {'str_sp': 'pearl and silver cufflinks'} @@ -54173,142 +54372,142 @@ msgstr "镶嵌珍珠的袖扣。" #: data/json/items/armor/jewelry.json msgid "garnet and silver cufflinks" msgid_plural "garnet and silver cufflinks" -msgstr[0] "" +msgstr[0] "石榴石銀袖扣" #: data/json/items/armor/jewelry.json msgid "diamond and silver cufflinks" msgid_plural "diamond and silver cufflinks" -msgstr[0] "" +msgstr[0] "鑽石銀袖扣" #: data/json/items/armor/jewelry.json msgid "amethyst and silver cufflinks" msgid_plural "amethyst and silver cufflinks" -msgstr[0] "" +msgstr[0] "紫水晶銀袖扣" #: data/json/items/armor/jewelry.json msgid "aquamarine and silver cufflinks" msgid_plural "aquamarine and silver cufflinks" -msgstr[0] "" +msgstr[0] "海藍寶石銀袖扣" #: data/json/items/armor/jewelry.json msgid "emerald and silver cufflinks" msgid_plural "emerald and silver cufflinks" -msgstr[0] "" +msgstr[0] "祖母綠銀袖扣" #: data/json/items/armor/jewelry.json msgid "alexandrite and silver cufflinks" msgid_plural "alexandrite and silver cufflinks" -msgstr[0] "" +msgstr[0] "紫翠玉銀袖扣" #: data/json/items/armor/jewelry.json msgid "ruby and silver cufflinks" msgid_plural "ruby and silver cufflinks" -msgstr[0] "" +msgstr[0] "紅寶石銀袖扣" #: data/json/items/armor/jewelry.json msgid "peridot and silver cufflinks" msgid_plural "peridot and silver cufflinks" -msgstr[0] "" +msgstr[0] "橄欖石銀袖扣" #: data/json/items/armor/jewelry.json msgid "sapphire and silver cufflinks" msgid_plural "sapphire and silver cufflinks" -msgstr[0] "" +msgstr[0] "藍寶石銀袖扣" #: data/json/items/armor/jewelry.json msgid "tourmaline and silver cufflinks" msgid_plural "tourmaline and silver cufflinks" -msgstr[0] "" +msgstr[0] "電氣石銀袖扣" #: data/json/items/armor/jewelry.json msgid "citrine and silver cufflinks" msgid_plural "citrine and silver cufflinks" -msgstr[0] "" +msgstr[0] "黃水晶銀袖扣" #: data/json/items/armor/jewelry.json msgid "blue topaz and silver cufflinks" msgid_plural "blue topaz and silver cufflinks" -msgstr[0] "" +msgstr[0] "藍黃玉銀袖扣" #: data/json/items/armor/jewelry.json msgid "opal and silver cufflinks" msgid_plural "opal and silver cufflinks" -msgstr[0] "" +msgstr[0] "蛋白石銀袖扣" #: data/json/items/armor/jewelry.json msgid "pearl and silver cufflinks" msgid_plural "pearl and silver cufflinks" -msgstr[0] "" +msgstr[0] "珍珠銀袖扣" #: data/json/items/armor/jewelry.json msgid "garnet and platinum cufflinks" msgid_plural "garnet and platinum cufflinks" -msgstr[0] "" +msgstr[0] "石榴石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "diamond and platinum cufflinks" msgid_plural "diamond and platinum cufflinks" -msgstr[0] "" +msgstr[0] "鑽石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "amethyst and platinum cufflinks" msgid_plural "amethyst and platinum cufflinks" -msgstr[0] "" +msgstr[0] "紫水晶鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum cufflinks" msgid_plural "aquamarine and platinum cufflinks" -msgstr[0] "" +msgstr[0] "海藍寶石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "emerald and platinum cufflinks" msgid_plural "emerald and platinum cufflinks" -msgstr[0] "" +msgstr[0] "祖母綠鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum cufflinks" msgid_plural "alexandrite and platinum cufflinks" -msgstr[0] "" +msgstr[0] "紫翠玉鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "ruby and platinum cufflinks" msgid_plural "ruby and platinum cufflinks" -msgstr[0] "" +msgstr[0] "紅寶石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "peridot and platinum cufflinks" msgid_plural "peridot and platinum cufflinks" -msgstr[0] "" +msgstr[0] "橄欖石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "sapphire and platinum cufflinks" msgid_plural "sapphire and platinum cufflinks" -msgstr[0] "" +msgstr[0] "藍寶石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum cufflinks" msgid_plural "tourmaline and platinum cufflinks" -msgstr[0] "" +msgstr[0] "電氣石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "citrine and platinum cufflinks" msgid_plural "citrine and platinum cufflinks" -msgstr[0] "" +msgstr[0] "黃水晶鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum cufflinks" msgid_plural "blue topaz and platinum cufflinks" -msgstr[0] "" +msgstr[0] "藍黃玉鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "opal and platinum cufflinks" msgid_plural "opal and platinum cufflinks" -msgstr[0] "" +msgstr[0] "蛋白石鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "pearl and platinum cufflinks" msgid_plural "pearl and platinum cufflinks" -msgstr[0] "" +msgstr[0] "珍珠鉑金袖扣" #: data/json/items/armor/jewelry.json msgid "plug" @@ -54992,7 +55191,7 @@ msgstr "一條光滑的黑色皮革尾巴, 掛著許多小珠子。當你走路 #: data/json/items/armor/jewelry.json msgid "pair of diamond and gold earrings" msgid_plural "pairs of diamond and gold earrings" -msgstr[0] "" +msgstr[0] "钻石金耳环" #. ~ Description for {'str': 'pair of diamond and gold earrings', 'str_pl': #. 'pairs of diamond and gold earrings'} @@ -55005,7 +55204,7 @@ msgstr "一对闪亮的钻石金耳环。你可以戴着它,但是不会有特 #: data/json/items/armor/jewelry.json msgid "pair of garnet and gold earrings" msgid_plural "pairs of garnet and gold earrings" -msgstr[0] "" +msgstr[0] "石榴石金耳环" #. ~ Description for {'str': 'pair of garnet and gold earrings', 'str_pl': #. 'pairs of garnet and gold earrings'} @@ -55018,7 +55217,7 @@ msgstr "一对闪亮的石榴石金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of amethyst and gold earrings" msgid_plural "pairs of amethyst and gold earrings" -msgstr[0] "" +msgstr[0] "紫水晶金耳环" #. ~ Description for {'str': 'pair of amethyst and gold earrings', 'str_pl': #. 'pairs of amethyst and gold earrings'} @@ -55031,7 +55230,7 @@ msgstr "一对闪亮的紫水晶金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of aquamarine and gold earrings" msgid_plural "pairs of aquamarine and gold earrings" -msgstr[0] "" +msgstr[0] "海蓝宝石金耳环" #. ~ Description for {'str': 'pair of aquamarine and gold earrings', 'str_pl': #. 'pairs of aquamarine and gold earrings'} @@ -55044,7 +55243,7 @@ msgstr "一对闪亮的海蓝宝石金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of emerald and gold earrings" msgid_plural "pairs of emerald and gold earrings" -msgstr[0] "" +msgstr[0] "祖母绿金耳环" #. ~ Description for {'str': 'pair of emerald and gold earrings', 'str_pl': #. 'pairs of emerald and gold earrings'} @@ -55057,7 +55256,7 @@ msgstr "一对闪亮的祖母绿金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of alexandrite and gold earrings" msgid_plural "pairs of alexandrite and gold earrings" -msgstr[0] "" +msgstr[0] "紫翠玉金耳环" #. ~ Description for {'str': 'pair of alexandrite and gold earrings', #. 'str_pl': 'pairs of alexandrite and gold earrings'} @@ -55070,7 +55269,7 @@ msgstr "一对闪亮的紫翠玉金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of ruby and gold earrings" msgid_plural "pairs of ruby and gold earrings" -msgstr[0] "" +msgstr[0] "红宝石金耳环" #. ~ Description for {'str': 'pair of ruby and gold earrings', 'str_pl': #. 'pairs of ruby and gold earrings'} @@ -55083,7 +55282,7 @@ msgstr "一对闪亮的红宝石金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of peridot and gold earrings" msgid_plural "pairs of peridot and gold earrings" -msgstr[0] "" +msgstr[0] "橄榄石金耳环" #. ~ Description for {'str': 'pair of peridot and gold earrings', 'str_pl': #. 'pairs of peridot and gold earrings'} @@ -55096,7 +55295,7 @@ msgstr "一对闪亮的橄榄石金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of sapphire and gold earrings" msgid_plural "pairs of sapphire and gold earrings" -msgstr[0] "" +msgstr[0] "蓝宝石金耳环" #. ~ Description for {'str': 'pair of sapphire and gold earrings', 'str_pl': #. 'pairs of sapphire and gold earrings'} @@ -55109,7 +55308,7 @@ msgstr "一对闪亮的蓝宝石金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of tourmaline and gold earrings" msgid_plural "pairs of tourmaline and gold earrings" -msgstr[0] "" +msgstr[0] "电气石金耳环" #. ~ Description for {'str': 'pair of tourmaline and gold earrings', 'str_pl': #. 'pairs of tourmaline and gold earrings'} @@ -55122,7 +55321,7 @@ msgstr "一对闪亮的电气石金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of citrine and gold earrings" msgid_plural "pairs of citrine and gold earrings" -msgstr[0] "" +msgstr[0] "黄水晶金耳环" #. ~ Description for {'str': 'pair of citrine and gold earrings', 'str_pl': #. 'pairs of citrine and gold earrings'} @@ -55135,7 +55334,7 @@ msgstr "一对闪亮的黄水晶金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of blue topaz and gold earrings" msgid_plural "pairs of blue topaz and gold earrings" -msgstr[0] "" +msgstr[0] "蓝黄玉金耳环" #. ~ Description for {'str': 'pair of blue topaz and gold earrings', 'str_pl': #. 'pairs of blue topaz and gold earrings'} @@ -55148,7 +55347,7 @@ msgstr "一对闪亮的蓝黄玉金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of opal and gold earrings" msgid_plural "pairs of opal and gold earrings" -msgstr[0] "" +msgstr[0] "蛋白石金耳环" #. ~ Description for {'str': 'pair of opal and gold earrings', 'str_pl': #. 'pairs of opal and gold earrings'} @@ -55161,7 +55360,7 @@ msgstr "一对闪亮的蛋白石金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of pearl and gold earrings" msgid_plural "pairs of pearl and gold earrings" -msgstr[0] "" +msgstr[0] "珍珠金耳环" #. ~ Description for {'str': 'pair of pearl and gold earrings', 'str_pl': #. 'pairs of pearl and gold earrings'} @@ -55174,7 +55373,7 @@ msgstr "一对闪亮的珍珠金耳环。你可以戴着它,但是不会有特 #: data/json/items/armor/jewelry.json msgid "pair of diamond and silver earrings" msgid_plural "pairs of diamond and silver earrings" -msgstr[0] "" +msgstr[0] "钻石银耳环" #. ~ Description for {'str': 'pair of diamond and silver earrings', 'str_pl': #. 'pairs of diamond and silver earrings'} @@ -55187,7 +55386,7 @@ msgstr "一对闪亮的钻石银耳环。你可以戴着它,但是不会有特 #: data/json/items/armor/jewelry.json msgid "pair of garnet and silver earrings" msgid_plural "pairs of garnet and silver earrings" -msgstr[0] "" +msgstr[0] "石榴石银耳环" #. ~ Description for {'str': 'pair of garnet and silver earrings', 'str_pl': #. 'pairs of garnet and silver earrings'} @@ -55200,7 +55399,7 @@ msgstr "一对闪亮石榴石银耳环。你可以戴着它,但是不会有特 #: data/json/items/armor/jewelry.json msgid "pair of amethyst and silver earrings" msgid_plural "pairs of amethyst and silver earrings" -msgstr[0] "" +msgstr[0] "紫水晶银耳环" #. ~ Description for {'str': 'pair of amethyst and silver earrings', 'str_pl': #. 'pairs of amethyst and silver earrings'} @@ -55213,7 +55412,7 @@ msgstr "一对闪亮的紫水晶银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of aquamarine and silver earrings" msgid_plural "pairs of aquamarine and silver earrings" -msgstr[0] "" +msgstr[0] "海蓝宝石银耳环" #. ~ Description for {'str': 'pair of aquamarine and silver earrings', #. 'str_pl': 'pairs of aquamarine and silver earrings'} @@ -55226,7 +55425,7 @@ msgstr "一对闪亮的海蓝宝石银耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of emerald and silver earrings" msgid_plural "pairs of emerald and silver earrings" -msgstr[0] "" +msgstr[0] "祖母绿银耳环" #. ~ Description for {'str': 'pair of emerald and silver earrings', 'str_pl': #. 'pairs of emerald and silver earrings'} @@ -55239,7 +55438,7 @@ msgstr "一对闪亮的祖母绿银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of alexandrite and silver earrings" msgid_plural "pairs of alexandrite and silver earrings" -msgstr[0] "" +msgstr[0] "紫翠玉银耳环" #. ~ Description for {'str': 'pair of alexandrite and silver earrings', #. 'str_pl': 'pairs of alexandrite and silver earrings'} @@ -55252,7 +55451,7 @@ msgstr "一对闪亮的紫翠玉银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of ruby and silver earrings" msgid_plural "pairs of ruby and silver earrings" -msgstr[0] "" +msgstr[0] "红宝石银耳环" #. ~ Description for {'str': 'pair of ruby and silver earrings', 'str_pl': #. 'pairs of ruby and silver earrings'} @@ -55265,7 +55464,7 @@ msgstr "一对闪亮的红宝石银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of peridot and silver earrings" msgid_plural "pairs of peridot and silver earrings" -msgstr[0] "" +msgstr[0] "橄榄石银耳环" #. ~ Description for {'str': 'pair of peridot and silver earrings', 'str_pl': #. 'pairs of peridot and silver earrings'} @@ -55278,7 +55477,7 @@ msgstr "一对闪亮的橄榄石银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of sapphire and silver earrings" msgid_plural "pairs of sapphire and silver earrings" -msgstr[0] "" +msgstr[0] "蓝宝石银耳环" #. ~ Description for {'str': 'pair of sapphire and silver earrings', 'str_pl': #. 'pairs of sapphire and silver earrings'} @@ -55291,7 +55490,7 @@ msgstr "一对闪亮的蓝宝石银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of tourmaline and silver earrings" msgid_plural "pairs of tourmaline and silver earrings" -msgstr[0] "" +msgstr[0] "电气石银耳环" #. ~ Description for {'str': 'pair of tourmaline and silver earrings', #. 'str_pl': 'pairs of tourmaline and silver earrings'} @@ -55304,7 +55503,7 @@ msgstr "一对闪亮的电气石银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of citrine and silver earrings" msgid_plural "pairs of citrine and silver earrings" -msgstr[0] "" +msgstr[0] "黄水晶银耳环" #. ~ Description for {'str': 'pair of citrine and silver earrings', 'str_pl': #. 'pairs of citrine and silver earrings'} @@ -55317,7 +55516,7 @@ msgstr "一对闪亮的黄水晶银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of blue topaz and silver earrings" msgid_plural "pairs of blue topaz and silver earrings" -msgstr[0] "" +msgstr[0] "蓝黄玉银耳环" #. ~ Description for {'str': 'pair of blue topaz and silver earrings', #. 'str_pl': 'pairs of blue topaz and silver earrings'} @@ -55330,7 +55529,7 @@ msgstr "一对闪亮的蓝黄玉银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of opal and silver earrings" msgid_plural "pairs of opal and silver earrings" -msgstr[0] "" +msgstr[0] "蛋白石银耳环" #. ~ Description for {'str': 'pair of opal and silver earrings', 'str_pl': #. 'pairs of opal and silver earrings'} @@ -55343,7 +55542,7 @@ msgstr "一对闪亮的蛋白石银耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of pearl and silver earrings" msgid_plural "pairs of pearl and silver earrings" -msgstr[0] "" +msgstr[0] "珍珠银耳环" #. ~ Description for {'str': 'pair of pearl and silver earrings', 'str_pl': #. 'pairs of pearl and silver earrings'} @@ -55356,7 +55555,7 @@ msgstr "一对闪亮的珍珠银耳环。你可以戴着它,但是不会有特 #: data/json/items/armor/jewelry.json msgid "pair of diamond and platinum earrings" msgid_plural "pairs of diamond and platinum earrings" -msgstr[0] "" +msgstr[0] "钻石铂金耳环" #. ~ Description for {'str': 'pair of diamond and platinum earrings', #. 'str_pl': 'pairs of diamond and platinum earrings'} @@ -55369,7 +55568,7 @@ msgstr "一对闪亮的钻石铂金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "pair of garnet and platinum earrings" msgid_plural "pairs of garnet and platinum earrings" -msgstr[0] "" +msgstr[0] "石榴石铂金耳环" #. ~ Description for {'str': 'pair of garnet and platinum earrings', 'str_pl': #. 'pairs of garnet and platinum earrings'} @@ -55382,7 +55581,7 @@ msgstr "一对闪亮的石榴石铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of amethyst and platinum earrings" msgid_plural "pairs of amethyst and platinum earrings" -msgstr[0] "" +msgstr[0] "紫水晶铂金耳环" #. ~ Description for {'str': 'pair of amethyst and platinum earrings', #. 'str_pl': 'pairs of amethyst and platinum earrings'} @@ -55395,7 +55594,7 @@ msgstr "一对闪亮的紫水晶铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of aquamarine and platinum earrings" msgid_plural "pairs of aquamarine and platinum earrings" -msgstr[0] "" +msgstr[0] "海蓝宝石铂金耳环" #. ~ Description for {'str': 'pair of aquamarine and platinum earrings', #. 'str_pl': 'pairs of aquamarine and platinum earrings'} @@ -55408,7 +55607,7 @@ msgstr "一对闪亮的海蓝宝石铂金耳环。你可以戴着它,但是不 #: data/json/items/armor/jewelry.json msgid "pair of emerald and platinum earrings" msgid_plural "pairs of emerald and platinum earrings" -msgstr[0] "" +msgstr[0] "祖母绿铂金耳环" #. ~ Description for {'str': 'pair of emerald and platinum earrings', #. 'str_pl': 'pairs of emerald and platinum earrings'} @@ -55421,7 +55620,7 @@ msgstr "一对闪亮的祖母绿铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of alexandrite and platinum earrings" msgid_plural "pairs of alexandrite and platinum earrings" -msgstr[0] "" +msgstr[0] "紫翠玉铂金耳环" #. ~ Description for {'str': 'pair of alexandrite and platinum earrings', #. 'str_pl': 'pairs of alexandrite and platinum earrings'} @@ -55434,7 +55633,7 @@ msgstr "一对闪亮的紫翠玉铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of ruby and platinum earrings" msgid_plural "pairs of ruby and platinum earrings" -msgstr[0] "" +msgstr[0] "红宝石铂金耳环" #. ~ Description for {'str': 'pair of ruby and platinum earrings', 'str_pl': #. 'pairs of ruby and platinum earrings'} @@ -55447,7 +55646,7 @@ msgstr "一对闪亮的红宝石铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of peridot and platinum earrings" msgid_plural "pairs of peridot and platinum earrings" -msgstr[0] "" +msgstr[0] "橄榄石铂金耳环" #. ~ Description for {'str': 'pair of peridot and platinum earrings', #. 'str_pl': 'pairs of peridot and platinum earrings'} @@ -55460,7 +55659,7 @@ msgstr "一对闪亮的橄榄石铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of sapphire and platinum earrings" msgid_plural "pairs of sapphire and platinum earrings" -msgstr[0] "" +msgstr[0] "蓝宝石铂金耳环" #. ~ Description for {'str': 'pair of sapphire and platinum earrings', #. 'str_pl': 'pairs of sapphire and platinum earrings'} @@ -55473,7 +55672,7 @@ msgstr "一对闪亮的蓝宝石铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of tourmaline and platinum earrings" msgid_plural "pairs of tourmaline and platinum earrings" -msgstr[0] "" +msgstr[0] "电气石铂金耳环" #. ~ Description for {'str': 'pair of tourmaline and platinum earrings', #. 'str_pl': 'pairs of tourmaline and platinum earrings'} @@ -55486,7 +55685,7 @@ msgstr "一对闪亮的电气石铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of citrine and platinum earrings" msgid_plural "pairs of citrine and platinum earrings" -msgstr[0] "" +msgstr[0] "黄水晶铂金耳环" #. ~ Description for {'str': 'pair of citrine and platinum earrings', #. 'str_pl': 'pairs of citrine and platinum earrings'} @@ -55499,7 +55698,7 @@ msgstr "一对闪亮的黄水晶铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of blue topaz and platinum earrings" msgid_plural "pairs of blue topaz and platinum earrings" -msgstr[0] "" +msgstr[0] "蓝黄玉铂金耳环" #. ~ Description for {'str': 'pair of blue topaz and platinum earrings', #. 'str_pl': 'pairs of blue topaz and platinum earrings'} @@ -55512,7 +55711,7 @@ msgstr "一对闪亮的蓝黄玉铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of opal and platinum earrings" msgid_plural "pairs of opal and platinum earrings" -msgstr[0] "" +msgstr[0] "蛋白石铂金耳环" #. ~ Description for {'str': 'pair of opal and platinum earrings', 'str_pl': #. 'pairs of opal and platinum earrings'} @@ -55525,7 +55724,7 @@ msgstr "一对闪亮的蛋白石铂金耳环。你可以戴着它,但是不会 #: data/json/items/armor/jewelry.json msgid "pair of pearl and platinum earrings" msgid_plural "pairs of pearl and platinum earrings" -msgstr[0] "" +msgstr[0] "珍珠铂金耳环" #. ~ Description for {'str': 'pair of pearl and platinum earrings', 'str_pl': #. 'pairs of pearl and platinum earrings'} @@ -55538,7 +55737,7 @@ msgstr "一对闪亮的珍珠铂金耳环。你可以戴着它,但是不会有 #: data/json/items/armor/jewelry.json msgid "garnet and gold ring" msgid_plural "garnet and gold rings" -msgstr[0] "" +msgstr[0] "石榴石金戒指" #. ~ Description for {'str': 'garnet and gold ring'} #: data/json/items/armor/jewelry.json @@ -55550,7 +55749,7 @@ msgstr "一只镶嵌着石榴石的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "amethyst and gold ring" msgid_plural "amethyst and gold rings" -msgstr[0] "" +msgstr[0] "紫水晶金戒指" #. ~ Description for {'str': 'amethyst and gold ring'} #: data/json/items/armor/jewelry.json @@ -55562,7 +55761,7 @@ msgstr "一只镶嵌着紫水晶的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "aquamarine and gold ring" msgid_plural "aquamarine and gold rings" -msgstr[0] "" +msgstr[0] "海蓝宝石金戒指" #. ~ Description for {'str': 'aquamarine and gold ring'} #: data/json/items/armor/jewelry.json @@ -55574,7 +55773,7 @@ msgstr "一只镶嵌着海蓝宝石的金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "emerald and gold ring" msgid_plural "emerald and gold rings" -msgstr[0] "" +msgstr[0] "祖母绿金戒指" #. ~ Description for {'str': 'emerald and gold ring'} #: data/json/items/armor/jewelry.json @@ -55586,7 +55785,7 @@ msgstr "一只镶嵌着祖母绿的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "alexandrite and gold ring" msgid_plural "alexandrite and gold rings" -msgstr[0] "" +msgstr[0] "紫翠玉金戒指" #. ~ Description for {'str': 'alexandrite and gold ring'} #: data/json/items/armor/jewelry.json @@ -55598,7 +55797,7 @@ msgstr "一只镶嵌着紫翠玉的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "ruby and gold ring" msgid_plural "ruby and gold rings" -msgstr[0] "" +msgstr[0] "红宝石金戒指" #. ~ Description for {'str': 'ruby and gold ring'} #: data/json/items/armor/jewelry.json @@ -55610,7 +55809,7 @@ msgstr "一只镶嵌着红宝石的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "peridot and gold ring" msgid_plural "peridot and gold rings" -msgstr[0] "" +msgstr[0] "橄榄石金戒指" #. ~ Description for {'str': 'peridot and gold ring'} #: data/json/items/armor/jewelry.json @@ -55622,7 +55821,7 @@ msgstr "一只镶嵌着橄榄石的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "sapphire and gold ring" msgid_plural "sapphire and gold rings" -msgstr[0] "" +msgstr[0] "蓝宝石金戒指" #. ~ Description for {'str': 'sapphire and gold ring'} #: data/json/items/armor/jewelry.json @@ -55634,7 +55833,7 @@ msgstr "一只镶嵌着蓝宝石的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "tourmaline and gold ring" msgid_plural "tourmaline and gold rings" -msgstr[0] "" +msgstr[0] "电气石金戒指" #. ~ Description for {'str': 'tourmaline and gold ring'} #: data/json/items/armor/jewelry.json @@ -55646,7 +55845,7 @@ msgstr "一只镶嵌着电气石的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "citrine and gold ring" msgid_plural "citrine and gold rings" -msgstr[0] "" +msgstr[0] "黄水晶金戒指" #. ~ Description for {'str': 'citrine and gold ring'} #: data/json/items/armor/jewelry.json @@ -55658,7 +55857,7 @@ msgstr "一只镶嵌着黄水晶的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "blue topaz and gold ring" msgid_plural "blue topaz and gold rings" -msgstr[0] "" +msgstr[0] "蓝黄玉金戒指" #. ~ Description for {'str': 'blue topaz and gold ring'} #: data/json/items/armor/jewelry.json @@ -55670,7 +55869,7 @@ msgstr "一只镶嵌着蓝黄玉的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "opal and gold ring" msgid_plural "opal and gold rings" -msgstr[0] "" +msgstr[0] "蛋白石金戒指" #. ~ Description for {'str': 'opal and gold ring'} #: data/json/items/armor/jewelry.json @@ -55682,7 +55881,7 @@ msgstr "一只镶嵌着蛋白石的金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "pearl and gold ring" msgid_plural "pearl and gold rings" -msgstr[0] "" +msgstr[0] "珍珠金戒指" #. ~ Description for {'str': 'pearl and gold ring'} #: data/json/items/armor/jewelry.json @@ -55694,7 +55893,7 @@ msgstr "一只镶嵌着珍珠的金戒指。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "diamond and silver ring" msgid_plural "diamond and silver rings" -msgstr[0] "" +msgstr[0] "钻石银戒指" #. ~ Description for {'str': 'diamond and silver ring'} #: data/json/items/armor/jewelry.json @@ -55706,7 +55905,7 @@ msgstr "一只镶嵌着钻石的银戒指。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "garnet and silver ring" msgid_plural "garnet and silver rings" -msgstr[0] "" +msgstr[0] "石榴石银戒指" #. ~ Description for {'str': 'garnet and silver ring'} #: data/json/items/armor/jewelry.json @@ -55718,7 +55917,7 @@ msgstr "一只镶嵌着石榴石的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "amethyst and silver ring" msgid_plural "amethyst and silver rings" -msgstr[0] "" +msgstr[0] "紫水晶银戒指" #. ~ Description for {'str': 'amethyst and silver ring'} #: data/json/items/armor/jewelry.json @@ -55730,7 +55929,7 @@ msgstr "一只镶嵌着紫水晶的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "aquamarine and silver ring" msgid_plural "aquamarine and silver rings" -msgstr[0] "" +msgstr[0] "海蓝宝石银戒指" #. ~ Description for {'str': 'aquamarine and silver ring'} #: data/json/items/armor/jewelry.json @@ -55742,7 +55941,7 @@ msgstr "一只镶嵌着海蓝宝石的银戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "emerald and silver ring" msgid_plural "emerald and silver rings" -msgstr[0] "" +msgstr[0] "祖母绿银戒指" #. ~ Description for {'str': 'emerald and silver ring'} #: data/json/items/armor/jewelry.json @@ -55754,7 +55953,7 @@ msgstr "一只镶嵌着祖母绿的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "alexandrite and silver ring" msgid_plural "alexandrite and silver rings" -msgstr[0] "" +msgstr[0] "紫翠玉银戒指" #. ~ Description for {'str': 'alexandrite and silver ring'} #: data/json/items/armor/jewelry.json @@ -55766,7 +55965,7 @@ msgstr "一只镶嵌着紫翠玉的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "ruby and silver ring" msgid_plural "ruby and silver rings" -msgstr[0] "" +msgstr[0] "红宝石银戒指" #. ~ Description for {'str': 'ruby and silver ring'} #: data/json/items/armor/jewelry.json @@ -55778,7 +55977,7 @@ msgstr "一只镶嵌着红宝石的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "peridot and silver ring" msgid_plural "peridot and silver rings" -msgstr[0] "" +msgstr[0] "橄榄石银戒指" #. ~ Description for {'str': 'peridot and silver ring'} #: data/json/items/armor/jewelry.json @@ -55790,7 +55989,7 @@ msgstr "一只镶嵌着橄榄石的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "sapphire and silver ring" msgid_plural "sapphire and silver rings" -msgstr[0] "" +msgstr[0] "蓝宝石银戒指" #. ~ Description for {'str': 'sapphire and silver ring'} #: data/json/items/armor/jewelry.json @@ -55802,7 +56001,7 @@ msgstr "一只镶嵌着蓝宝石的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "tourmaline and silver ring" msgid_plural "tourmaline and silver rings" -msgstr[0] "" +msgstr[0] "电气石银戒指" #. ~ Description for {'str': 'tourmaline and silver ring'} #: data/json/items/armor/jewelry.json @@ -55814,7 +56013,7 @@ msgstr "一只镶嵌着电气石的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "citrine and silver ring" msgid_plural "citrine and silver rings" -msgstr[0] "" +msgstr[0] "黄水晶银戒指" #. ~ Description for {'str': 'citrine and silver ring'} #: data/json/items/armor/jewelry.json @@ -55826,7 +56025,7 @@ msgstr "一只镶嵌着黄水晶的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "blue topaz and silver ring" msgid_plural "blue topaz and silver rings" -msgstr[0] "" +msgstr[0] "蓝黄玉银戒指" #. ~ Description for {'str': 'blue topaz and silver ring'} #: data/json/items/armor/jewelry.json @@ -55838,7 +56037,7 @@ msgstr "一只镶嵌着蓝黄玉的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "opal and silver ring" msgid_plural "opal and silver rings" -msgstr[0] "" +msgstr[0] "蛋白石银戒指" #. ~ Description for {'str': 'opal and silver ring'} #: data/json/items/armor/jewelry.json @@ -55850,7 +56049,7 @@ msgstr "一只镶嵌着蛋白石的银戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "pearl and silver ring" msgid_plural "pearl and silver rings" -msgstr[0] "" +msgstr[0] "珍珠银戒指" #. ~ Description for {'str': 'pearl and silver ring'} #: data/json/items/armor/jewelry.json @@ -55862,7 +56061,7 @@ msgstr "一只镶嵌着珍珠的银戒指。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "diamond and platinum ring" msgid_plural "diamond and platinum rings" -msgstr[0] "" +msgstr[0] "钻石铂金戒指" #. ~ Description for {'str': 'diamond and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55874,7 +56073,7 @@ msgstr "一只镶嵌着钻石的铂金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "garnet and platinum ring" msgid_plural "garnet and platinum rings" -msgstr[0] "" +msgstr[0] "石榴石铂金戒指" #. ~ Description for {'str': 'garnet and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55886,7 +56085,7 @@ msgstr "一只镶嵌着石榴石的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "amethyst and platinum ring" msgid_plural "amethyst and platinum rings" -msgstr[0] "" +msgstr[0] "紫水晶铂金戒指" #. ~ Description for {'str': 'amethyst and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55898,7 +56097,7 @@ msgstr "一只镶嵌着紫水晶的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum ring" msgid_plural "aquamarine and platinum rings" -msgstr[0] "" +msgstr[0] "海蓝宝石铂金戒指" #. ~ Description for {'str': 'aquamarine and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55910,7 +56109,7 @@ msgstr "一只镶嵌着海蓝宝石的铂金戒指。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "emerald and platinum ring" msgid_plural "emerald and platinum rings" -msgstr[0] "" +msgstr[0] "祖母绿铂金戒指" #. ~ Description for {'str': 'emerald and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55922,7 +56121,7 @@ msgstr "一只镶嵌着祖母绿的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum ring" msgid_plural "alexandrite and platinum rings" -msgstr[0] "" +msgstr[0] "紫翠玉铂金戒指" #. ~ Description for {'str': 'alexandrite and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55934,7 +56133,7 @@ msgstr "一只镶嵌着紫翠玉的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "ruby and platinum ring" msgid_plural "ruby and platinum rings" -msgstr[0] "" +msgstr[0] "红宝石铂金戒指" #. ~ Description for {'str': 'ruby and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55946,7 +56145,7 @@ msgstr "一只镶嵌着红宝石的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "peridot and platinum ring" msgid_plural "peridot and platinum rings" -msgstr[0] "" +msgstr[0] "橄榄石铂金戒指" #. ~ Description for {'str': 'peridot and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55958,7 +56157,7 @@ msgstr "一只镶嵌着橄榄石的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "sapphire and platinum ring" msgid_plural "sapphire and platinum rings" -msgstr[0] "" +msgstr[0] "蓝宝石铂金戒指" #. ~ Description for {'str': 'sapphire and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55970,7 +56169,7 @@ msgstr "一只镶嵌着蓝宝石的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum ring" msgid_plural "tourmaline and platinum rings" -msgstr[0] "" +msgstr[0] "电气石铂金戒指" #. ~ Description for {'str': 'tourmaline and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55982,7 +56181,7 @@ msgstr "一只镶嵌着电气石的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "citrine and platinum ring" msgid_plural "citrine and platinum rings" -msgstr[0] "" +msgstr[0] "黄水晶铂金戒指" #. ~ Description for {'str': 'citrine and platinum ring'} #: data/json/items/armor/jewelry.json @@ -55994,7 +56193,7 @@ msgstr "一只镶嵌着黄水晶的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum ring" msgid_plural "blue topaz and platinum rings" -msgstr[0] "" +msgstr[0] "蓝黄玉铂金戒指" #. ~ Description for {'str': 'blue topaz and platinum ring'} #: data/json/items/armor/jewelry.json @@ -56006,7 +56205,7 @@ msgstr "一只镶嵌着蓝黄玉的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "opal and platinum ring" msgid_plural "opal and platinum rings" -msgstr[0] "" +msgstr[0] "蛋白石铂金戒指" #. ~ Description for {'str': 'opal and platinum ring'} #: data/json/items/armor/jewelry.json @@ -56018,7 +56217,7 @@ msgstr "一只镶嵌着蛋白石的铂金戒指。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "pearl and platinum ring" msgid_plural "pearl and platinum rings" -msgstr[0] "" +msgstr[0] "珍珠铂金戒指" #. ~ Description for {'str': 'pearl and platinum ring'} #: data/json/items/armor/jewelry.json @@ -56030,7 +56229,7 @@ msgstr "一只镶嵌着珍珠的铂金戒指。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "diamond and gold bracelet" msgid_plural "diamond and gold bracelets" -msgstr[0] "" +msgstr[0] "钻石金手镯" #. ~ Description for {'str': 'diamond and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56042,7 +56241,7 @@ msgstr "一个镶嵌着闪亮钻石的金手镯。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "garnet and gold bracelet" msgid_plural "garnet and gold bracelets" -msgstr[0] "" +msgstr[0] "石榴石金手镯" #. ~ Description for {'str': 'garnet and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56054,7 +56253,7 @@ msgstr "一个镶嵌着闪亮石榴石的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "amethyst and gold bracelet" msgid_plural "amethyst and gold bracelets" -msgstr[0] "" +msgstr[0] "紫水晶金手镯" #. ~ Description for {'str': 'amethyst and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56066,7 +56265,7 @@ msgstr "一个镶嵌着闪亮紫水晶的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "aquamarine and gold bracelet" msgid_plural "aquamarine and gold bracelets" -msgstr[0] "" +msgstr[0] "海蓝宝石金手镯" #. ~ Description for {'str': 'aquamarine and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56078,7 +56277,7 @@ msgstr "一个镶嵌着闪亮海蓝宝石的金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "emerald and gold bracelet" msgid_plural "emerald and gold bracelets" -msgstr[0] "" +msgstr[0] "祖母绿金手镯" #. ~ Description for {'str': 'emerald and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56090,7 +56289,7 @@ msgstr "一个镶嵌着闪亮祖母绿的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "alexandrite and gold bracelet" msgid_plural "alexandrite and gold bracelets" -msgstr[0] "" +msgstr[0] "紫翠玉金手镯" #. ~ Description for {'str': 'alexandrite and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56102,7 +56301,7 @@ msgstr "一个镶嵌着闪亮紫翠玉的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "ruby and gold bracelet" msgid_plural "ruby and gold bracelets" -msgstr[0] "" +msgstr[0] "红宝石金手镯" #. ~ Description for {'str': 'ruby and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56114,7 +56313,7 @@ msgstr "一个镶嵌着闪亮红宝石的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "peridot and gold bracelet" msgid_plural "peridot and gold bracelets" -msgstr[0] "" +msgstr[0] "橄榄石金手镯" #. ~ Description for {'str': 'peridot and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56126,7 +56325,7 @@ msgstr "一个镶嵌着闪亮橄榄石的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "sapphire and gold bracelet" msgid_plural "sapphire and gold bracelets" -msgstr[0] "" +msgstr[0] "蓝宝石金手镯" #. ~ Description for {'str': 'sapphire and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56138,7 +56337,7 @@ msgstr "一个镶嵌着闪亮蓝宝石的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "tourmaline and gold bracelet" msgid_plural "tourmaline and gold bracelets" -msgstr[0] "" +msgstr[0] "电气石金手镯" #. ~ Description for {'str': 'tourmaline and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56150,7 +56349,7 @@ msgstr "一个镶嵌着闪亮电气石的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "citrine and gold bracelet" msgid_plural "citrine and gold bracelets" -msgstr[0] "" +msgstr[0] "黄水晶金手镯" #. ~ Description for {'str': 'citrine and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56162,7 +56361,7 @@ msgstr "一个镶嵌着闪亮黄水晶的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "blue topaz and gold bracelet" msgid_plural "blue topaz and gold bracelets" -msgstr[0] "" +msgstr[0] "蓝黄玉金手镯" #. ~ Description for {'str': 'blue topaz and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56174,7 +56373,7 @@ msgstr "一个镶嵌着闪亮蓝黄玉的金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "opal and gold bracelet" msgid_plural "opal and gold bracelets" -msgstr[0] "" +msgstr[0] "蛋白石金手镯" #. ~ Description for {'str': 'opal and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56186,7 +56385,7 @@ msgstr "一个镶嵌着蛋白石的金手镯。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "pearl and gold bracelet" msgid_plural "pearl and gold bracelets" -msgstr[0] "" +msgstr[0] "珍珠金手镯" #. ~ Description for {'str': 'pearl and gold bracelet'} #: data/json/items/armor/jewelry.json @@ -56198,7 +56397,7 @@ msgstr "一个镶嵌着珍珠的金手镯。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "diamond and silver bracelet" msgid_plural "diamond and silver bracelets" -msgstr[0] "" +msgstr[0] "钻石银手镯" #. ~ Description for {'str': 'diamond and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56210,7 +56409,7 @@ msgstr "一个镶嵌着闪亮钻石的银手镯。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "garnet and silver bracelet" msgid_plural "garnet and silver bracelets" -msgstr[0] "" +msgstr[0] "石榴石银手镯" #. ~ Description for {'str': 'garnet and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56222,7 +56421,7 @@ msgstr "一个镶嵌着闪亮石榴石的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "amethyst and silver bracelet" msgid_plural "amethyst and silver bracelets" -msgstr[0] "" +msgstr[0] "紫水晶银手镯" #. ~ Description for {'str': 'amethyst and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56234,7 +56433,7 @@ msgstr "一个镶嵌着闪亮紫水晶的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "aquamarine and silver bracelet" msgid_plural "aquamarine and silver bracelets" -msgstr[0] "" +msgstr[0] "海蓝宝石银手镯" #. ~ Description for {'str': 'aquamarine and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56246,7 +56445,7 @@ msgstr "一个镶嵌着闪亮海蓝宝石的银手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "emerald and silver bracelet" msgid_plural "emerald and silver bracelets" -msgstr[0] "" +msgstr[0] "祖母绿银手镯" #. ~ Description for {'str': 'emerald and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56258,7 +56457,7 @@ msgstr "一个镶嵌着闪亮祖母绿的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "alexandrite and silver bracelet" msgid_plural "alexandrite and silver bracelets" -msgstr[0] "" +msgstr[0] "紫翠玉银手镯" #. ~ Description for {'str': 'alexandrite and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56270,7 +56469,7 @@ msgstr "一个镶嵌着闪亮紫翠玉的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "ruby and silver bracelet" msgid_plural "ruby and silver bracelets" -msgstr[0] "" +msgstr[0] "红宝石银手镯" #. ~ Description for {'str': 'ruby and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56282,7 +56481,7 @@ msgstr "一个镶嵌着闪亮红宝石的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "peridot and silver bracelet" msgid_plural "peridot and silver bracelets" -msgstr[0] "" +msgstr[0] "橄榄石银手镯" #. ~ Description for {'str': 'peridot and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56294,7 +56493,7 @@ msgstr "一个镶嵌着闪亮橄榄石的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "sapphire and silver bracelet" msgid_plural "sapphire and silver bracelets" -msgstr[0] "" +msgstr[0] "蓝宝石银手镯" #. ~ Description for {'str': 'sapphire and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56306,7 +56505,7 @@ msgstr "一个镶嵌着闪亮蓝宝石的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "tourmaline and silver bracelet" msgid_plural "tourmaline and silver bracelets" -msgstr[0] "" +msgstr[0] "电气石银手镯" #. ~ Description for {'str': 'tourmaline and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56318,7 +56517,7 @@ msgstr "一个镶嵌着闪亮电气石的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "citrine and silver bracelet" msgid_plural "citrine and silver bracelets" -msgstr[0] "" +msgstr[0] "黄水晶银手镯" #. ~ Description for {'str': 'citrine and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56330,7 +56529,7 @@ msgstr "一个镶嵌着闪亮黄水晶的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "blue topaz and silver bracelet" msgid_plural "blue topaz and silver bracelets" -msgstr[0] "" +msgstr[0] "蓝黄玉银手镯" #. ~ Description for {'str': 'blue topaz and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56342,7 +56541,7 @@ msgstr "一个镶嵌着闪亮蓝黄玉的银手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "opal and silver bracelet" msgid_plural "opal and silver bracelets" -msgstr[0] "" +msgstr[0] "蛋白石银手镯" #. ~ Description for {'str': 'opal and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56354,7 +56553,7 @@ msgstr "一个镶嵌着蛋白石的银手镯。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "pearl and silver bracelet" msgid_plural "pearl and silver bracelets" -msgstr[0] "" +msgstr[0] "珍珠银手镯" #. ~ Description for {'str': 'pearl and silver bracelet'} #: data/json/items/armor/jewelry.json @@ -56366,7 +56565,7 @@ msgstr "一个镶嵌着珍珠的银手镯。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "diamond and platinum bracelet" msgid_plural "diamond and platinum bracelets" -msgstr[0] "" +msgstr[0] "钻石铂金手镯" #. ~ Description for {'str': 'diamond and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56378,7 +56577,7 @@ msgstr "一个镶嵌着闪亮钻石的铂金手镯。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "garnet and platinum bracelet" msgid_plural "garnet and platinum bracelets" -msgstr[0] "" +msgstr[0] "石榴石铂金手镯" #. ~ Description for {'str': 'garnet and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56390,7 +56589,7 @@ msgstr "一个镶嵌着闪亮石榴石的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "amethyst and platinum bracelet" msgid_plural "amethyst and platinum bracelets" -msgstr[0] "" +msgstr[0] "紫水晶铂金手镯" #. ~ Description for {'str': 'amethyst and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56402,7 +56601,7 @@ msgstr "一个镶嵌着闪亮紫水晶的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum bracelet" msgid_plural "aquamarine and platinum bracelets" -msgstr[0] "" +msgstr[0] "海蓝宝石铂金手镯" #. ~ Description for {'str': 'aquamarine and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56414,7 +56613,7 @@ msgstr "一个镶嵌着闪亮海蓝宝石的铂金手镯。你可以戴上它, #: data/json/items/armor/jewelry.json msgid "emerald and platinum bracelet" msgid_plural "emerald and platinum bracelets" -msgstr[0] "" +msgstr[0] "祖母绿铂金手镯" #. ~ Description for {'str': 'emerald and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56426,7 +56625,7 @@ msgstr "一个镶嵌着闪亮祖母绿的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum bracelet" msgid_plural "alexandrite and platinum bracelets" -msgstr[0] "" +msgstr[0] "紫翠玉铂金手镯" #. ~ Description for {'str': 'alexandrite and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56438,7 +56637,7 @@ msgstr "一个镶嵌着闪亮紫翠玉的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "ruby and platinum bracelet" msgid_plural "ruby and platinum bracelets" -msgstr[0] "" +msgstr[0] "红宝石铂金手镯" #. ~ Description for {'str': 'ruby and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56450,7 +56649,7 @@ msgstr "一个镶嵌着闪亮红宝石的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "peridot and platinum bracelet" msgid_plural "peridot and platinum bracelets" -msgstr[0] "" +msgstr[0] "橄榄石铂金手镯" #. ~ Description for {'str': 'peridot and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56462,7 +56661,7 @@ msgstr "一个镶嵌着闪亮橄榄石的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "sapphire and platinum bracelet" msgid_plural "sapphire and platinum bracelets" -msgstr[0] "" +msgstr[0] "蓝宝石铂金手镯" #. ~ Description for {'str': 'sapphire and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56474,7 +56673,7 @@ msgstr "一个镶嵌着闪亮蓝宝石的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum bracelet" msgid_plural "tourmaline and platinum bracelets" -msgstr[0] "" +msgstr[0] "电气石铂金手镯" #. ~ Description for {'str': 'tourmaline and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56486,7 +56685,7 @@ msgstr "一个镶嵌着闪亮电气石的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "citrine and platinum bracelet" msgid_plural "citrine and platinum bracelets" -msgstr[0] "" +msgstr[0] "黄水晶铂金手镯" #. ~ Description for {'str': 'citrine and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56498,7 +56697,7 @@ msgstr "一个镶嵌着闪亮黄水晶的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum bracelet" msgid_plural "blue topaz and platinum bracelets" -msgstr[0] "" +msgstr[0] "蓝黄玉铂金手镯" #. ~ Description for {'str': 'blue topaz and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56510,7 +56709,7 @@ msgstr "一个镶嵌着闪亮蓝黄玉的铂金手镯。你可以戴上它,但 #: data/json/items/armor/jewelry.json msgid "opal and platinum bracelet" msgid_plural "opal and platinum bracelets" -msgstr[0] "" +msgstr[0] "蛋白石铂金手镯" #. ~ Description for {'str': 'opal and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56522,7 +56721,7 @@ msgstr "一个镶嵌着蛋白石的铂金手镯。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "pearl and platinum bracelet" msgid_plural "pearl and platinum bracelets" -msgstr[0] "" +msgstr[0] "珍珠铂金手镯" #. ~ Description for {'str': 'pearl and platinum bracelet'} #: data/json/items/armor/jewelry.json @@ -56534,7 +56733,7 @@ msgstr "一个镶嵌着珍珠的铂金手镯。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "garnet and gold necklace" msgid_plural "garnet and gold necklaces" -msgstr[0] "" +msgstr[0] "石榴石金项链" #. ~ Description for {'str': 'garnet and gold necklace'} #: data/json/items/armor/jewelry.json @@ -56546,7 +56745,7 @@ msgstr "一串闪亮的镶石榴石金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "diamond and gold pendant necklace" msgid_plural "diamond and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "钻石金项链" #. ~ Description for {'str': 'diamond and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56558,7 +56757,7 @@ msgstr "一串闪亮的镶钻石金项链。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "amethyst and gold pendant necklace" msgid_plural "amethyst and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "紫水晶金项链" #. ~ Description for {'str': 'amethyst and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56570,7 +56769,7 @@ msgstr "一串闪亮的镶紫水晶金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "aquamarine and gold pendant necklace" msgid_plural "aquamarine and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "海蓝宝石金项链" #. ~ Description for {'str': 'aquamarine and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56582,7 +56781,7 @@ msgstr "一串闪亮的镶海蓝宝石金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "emerald and gold pendant necklace" msgid_plural "emerald and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "祖母绿金项链" #. ~ Description for {'str': 'emerald and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56594,7 +56793,7 @@ msgstr "一串闪亮的镶祖母绿金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "alexandrite and gold pendant necklace" msgid_plural "alexandrite and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "紫翠玉金项链" #. ~ Description for {'str': 'alexandrite and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56606,7 +56805,7 @@ msgstr "一串闪亮的镶紫翠玉金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "ruby and gold pendant necklace" msgid_plural "ruby and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "红宝石金项链" #. ~ Description for {'str': 'ruby and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56618,7 +56817,7 @@ msgstr "一串闪亮的镶红宝石金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "peridot and gold pendant necklace" msgid_plural "peridot and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "橄榄石金项链" #. ~ Description for {'str': 'peridot and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56630,7 +56829,7 @@ msgstr "一串闪亮的镶橄榄石金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "sapphire and gold pendant necklace" msgid_plural "sapphire and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "蓝宝石金项链" #. ~ Description for {'str': 'sapphire and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56642,7 +56841,7 @@ msgstr "一串闪亮的镶蓝宝石金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "tourmaline and gold pendant necklace" msgid_plural "tourmaline and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "电气石金项链" #. ~ Description for {'str': 'tourmaline and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56654,7 +56853,7 @@ msgstr "一串闪亮的镶电气石金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "citrine and gold pendant necklace" msgid_plural "citrine and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "黄水晶金项链" #. ~ Description for {'str': 'citrine and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56666,7 +56865,7 @@ msgstr "一串闪亮的镶黄水晶金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "blue topaz and gold pendant necklace" msgid_plural "blue topaz and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "蓝黄玉金项链" #. ~ Description for {'str': 'blue topaz and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56678,7 +56877,7 @@ msgstr "一串闪亮的镶蓝黄玉金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "opal and gold pendant necklace" msgid_plural "opal and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "蛋白石金项链" #. ~ Description for {'str': 'opal and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56690,7 +56889,7 @@ msgstr "一串闪亮的镶蛋白石金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "pearl and gold pendant necklace" msgid_plural "pearl and gold pendant necklaces" -msgstr[0] "" +msgstr[0] "珍珠金项链" #. ~ Description for {'str': 'pearl and gold pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56702,7 +56901,7 @@ msgstr "一串闪亮的镶珍珠金项链。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "garnet and silver necklace" msgid_plural "garnet and silver necklaces" -msgstr[0] "" +msgstr[0] "石榴石银项链" #. ~ Description for {'str': 'garnet and silver necklace'} #: data/json/items/armor/jewelry.json @@ -56714,7 +56913,7 @@ msgstr "一串闪亮的镶石榴石银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "diamond and silver pendant necklace" msgid_plural "diamond and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "钻石银项链" #. ~ Description for {'str': 'diamond and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56726,7 +56925,7 @@ msgstr "一串闪亮的镶钻石银项链。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "amethyst and silver pendant necklace" msgid_plural "amethyst and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "紫水晶银项链" #. ~ Description for {'str': 'amethyst and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56738,7 +56937,7 @@ msgstr "一串闪亮的镶紫水晶银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "aquamarine and silver pendant necklace" msgid_plural "aquamarine and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "海蓝宝石银项链" #. ~ Description for {'str': 'aquamarine and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56750,7 +56949,7 @@ msgstr "一串闪亮的镶海蓝宝石银项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "emerald and silver pendant necklace" msgid_plural "emerald and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "祖母绿银项链" #. ~ Description for {'str': 'emerald and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56762,7 +56961,7 @@ msgstr "一串闪亮的镶祖母绿银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "alexandrite and silver pendant necklace" msgid_plural "alexandrite and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "紫翠玉银项链" #. ~ Description for {'str': 'alexandrite and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56774,7 +56973,7 @@ msgstr "一串闪亮的镶紫翠玉银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "ruby and silver pendant necklace" msgid_plural "ruby and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "红宝石银项链" #. ~ Description for {'str': 'ruby and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56786,7 +56985,7 @@ msgstr "一串闪亮的镶红宝石银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "peridot and silver pendant necklace" msgid_plural "peridot and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "橄榄石银项链" #. ~ Description for {'str': 'peridot and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56798,7 +56997,7 @@ msgstr "一串闪亮的镶橄榄石银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "sapphire and silver pendant necklace" msgid_plural "sapphire and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "蓝宝石银项链" #. ~ Description for {'str': 'sapphire and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56810,7 +57009,7 @@ msgstr "一串闪亮的镶蓝宝石银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "tourmaline and silver pendant necklace" msgid_plural "tourmaline and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "电气石银项链" #. ~ Description for {'str': 'tourmaline and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56822,7 +57021,7 @@ msgstr "一串闪亮的镶电气石银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "citrine and silver pendant necklace" msgid_plural "citrine and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "黄水晶银项链" #. ~ Description for {'str': 'citrine and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56834,7 +57033,7 @@ msgstr "一串闪亮的镶黄水晶银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "blue topaz and silver pendant necklace" msgid_plural "blue topaz and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "蓝黄玉银项链" #. ~ Description for {'str': 'blue topaz and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56846,7 +57045,7 @@ msgstr "一串闪亮的镶蓝黄玉银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "opal and silver pendant necklace" msgid_plural "opal and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "蛋白石银项链" #. ~ Description for {'str': 'opal and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56858,7 +57057,7 @@ msgstr "一串闪亮的镶蛋白石银项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "pearl and silver pendant necklace" msgid_plural "pearl and silver pendant necklaces" -msgstr[0] "" +msgstr[0] "珍珠银项链" #. ~ Description for {'str': 'pearl and silver pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56870,7 +57069,7 @@ msgstr "一串闪亮的镶珍珠银项链。你可以戴上它,但是不会有 #: data/json/items/armor/jewelry.json msgid "garnet and platinum necklace" msgid_plural "garnet and platinum necklaces" -msgstr[0] "" +msgstr[0] "石榴石铂金项链" #. ~ Description for {'str': 'garnet and platinum necklace'} #: data/json/items/armor/jewelry.json @@ -56882,7 +57081,7 @@ msgstr "一串闪亮的镶石榴石铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "diamond and platinum pendant necklace" msgid_plural "diamond and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "钻石铂金项链" #. ~ Description for {'str': 'diamond and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56894,7 +57093,7 @@ msgstr "一串闪亮的镶钻石铂金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "amethyst and platinum pendant necklace" msgid_plural "amethyst and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "紫水晶铂金项链" #. ~ Description for {'str': 'amethyst and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56906,7 +57105,7 @@ msgstr "一串闪亮的镶紫水晶铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum pendant necklace" msgid_plural "aquamarine and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "海蓝宝石铂金项链" #. ~ Description for {'str': 'aquamarine and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56918,7 +57117,7 @@ msgstr "一串闪亮的镶海蓝宝石铂金项链。你可以戴上它,但是 #: data/json/items/armor/jewelry.json msgid "emerald and platinum pendant necklace" msgid_plural "emerald and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "祖母绿铂金项链" #. ~ Description for {'str': 'emerald and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56930,7 +57129,7 @@ msgstr "一串闪亮的镶祖母绿铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum pendant necklace" msgid_plural "alexandrite and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "紫翠玉铂金项链" #. ~ Description for {'str': 'alexandrite and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56942,7 +57141,7 @@ msgstr "一串闪亮的镶紫翠玉铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "ruby and platinum pendant necklace" msgid_plural "ruby and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "红宝石铂金项链" #. ~ Description for {'str': 'ruby and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56954,7 +57153,7 @@ msgstr "一串闪亮的镶红宝石铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "peridot and platinum pendant necklace" msgid_plural "peridot and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "橄榄石铂金项链" #. ~ Description for {'str': 'peridot and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56966,7 +57165,7 @@ msgstr "一串闪亮的镶橄榄石铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "sapphire and platinum pendant necklace" msgid_plural "sapphire and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "蓝宝石铂金项链" #. ~ Description for {'str': 'sapphire and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56978,7 +57177,7 @@ msgstr "一串闪亮的镶蓝宝石铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum pendant necklace" msgid_plural "tourmaline and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "电气石铂金项链" #. ~ Description for {'str': 'tourmaline and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -56990,7 +57189,7 @@ msgstr "一串闪亮的镶电气石铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "citrine and platinum pendant necklace" msgid_plural "citrine and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "黄水晶铂金项链" #. ~ Description for {'str': 'citrine and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -57002,7 +57201,7 @@ msgstr "一串闪亮的镶黄水晶铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum pendant necklace" msgid_plural "blue topaz and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "蓝黄玉铂金项链" #. ~ Description for {'str': 'blue topaz and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -57014,7 +57213,7 @@ msgstr "一串闪亮的镶蓝黄玉铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "opal and platinum pendant necklace" msgid_plural "opal and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "蛋白石铂金项链" #. ~ Description for {'str': 'opal and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -57026,7 +57225,7 @@ msgstr "一串闪亮的镶蛋白石铂金项链。你可以戴上它,但是不 #: data/json/items/armor/jewelry.json msgid "pearl and platinum pendant necklace" msgid_plural "pearl and platinum pendant necklaces" -msgstr[0] "" +msgstr[0] "珍珠铂金项链" #. ~ Description for {'str': 'pearl and platinum pendant necklace'} #: data/json/items/armor/jewelry.json @@ -57038,7 +57237,7 @@ msgstr "一串闪亮的镶珍珠铂金项链。你可以戴上它,但是不会 #: data/json/items/armor/jewelry.json msgid "garnet and platinum tiara" msgid_plural "garnet and platinum tiaras" -msgstr[0] "" +msgstr[0] "石榴石铂金王冠" #. ~ Description for {'str': 'garnet and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57048,7 +57247,7 @@ msgstr "一顶闪亮的镶有石榴石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "diamond and platinum tiara" msgid_plural "diamond and platinum tiaras" -msgstr[0] "" +msgstr[0] "钻石铂金王冠" #. ~ Description for {'str': 'diamond and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57058,7 +57257,7 @@ msgstr "一顶闪亮的镶有钻石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "amethyst and platinum tiara" msgid_plural "amethyst and platinum tiaras" -msgstr[0] "" +msgstr[0] "紫水晶铂金王冠" #. ~ Description for {'str': 'amethyst and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57068,7 +57267,7 @@ msgstr "一顶闪亮的镶有紫水晶的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "aquamarine and platinum tiara" msgid_plural "aquamarine and platinum tiaras" -msgstr[0] "" +msgstr[0] "海蓝宝石铂金王冠" #. ~ Description for {'str': 'aquamarine and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57078,7 +57277,7 @@ msgstr "一顶闪亮的镶有海蓝宝石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "emerald and platinum tiara" msgid_plural "emerald and platinum tiaras" -msgstr[0] "" +msgstr[0] "祖母绿铂金王冠" #. ~ Description for {'str': 'emerald and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57088,7 +57287,7 @@ msgstr "一顶闪亮的镶有祖母绿的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "alexandrite and platinum tiara" msgid_plural "alexandrite and platinum tiaras" -msgstr[0] "" +msgstr[0] "紫翠玉铂金王冠" #. ~ Description for {'str': 'alexandrite and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57098,7 +57297,7 @@ msgstr "一顶闪亮的镶有紫翠玉的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "ruby and platinum tiara" msgid_plural "ruby and platinum tiaras" -msgstr[0] "" +msgstr[0] "红宝石铂金王冠" #. ~ Description for {'str': 'ruby and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57108,7 +57307,7 @@ msgstr "一顶闪亮的镶有红宝石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "peridot and platinum tiara" msgid_plural "peridot and platinum tiaras" -msgstr[0] "" +msgstr[0] "橄榄石铂金王冠" #. ~ Description for {'str': 'peridot and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57118,7 +57317,7 @@ msgstr "一顶闪亮的镶有橄榄石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "sapphire and platinum tiara" msgid_plural "sapphire and platinum tiaras" -msgstr[0] "" +msgstr[0] "蓝宝石铂金王冠" #. ~ Description for {'str': 'sapphire and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57128,7 +57327,7 @@ msgstr "一顶闪亮的镶有蓝宝石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "tourmaline and platinum tiara" msgid_plural "tourmaline and platinum tiaras" -msgstr[0] "" +msgstr[0] "电气石铂金王冠" #. ~ Description for {'str': 'tourmaline and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57138,7 +57337,7 @@ msgstr "一顶闪亮的镶有电气石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "citrine and platinum tiara" msgid_plural "citrine and platinum tiaras" -msgstr[0] "" +msgstr[0] "黄水晶铂金王冠" #. ~ Description for {'str': 'citrine and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57148,7 +57347,7 @@ msgstr "一顶闪亮的镶有黄水晶的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "blue topaz and platinum tiara" msgid_plural "blue topaz and platinum tiaras" -msgstr[0] "" +msgstr[0] "蓝黄玉铂金王冠" #. ~ Description for {'str': 'blue topaz and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57158,7 +57357,7 @@ msgstr "一顶闪亮的镶有蓝黄玉的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "opal and platinum tiara" msgid_plural "opal and platinum tiaras" -msgstr[0] "" +msgstr[0] "蛋白石铂金王冠" #. ~ Description for {'str': 'opal and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57168,7 +57367,7 @@ msgstr "一顶闪亮的镶有蛋白石的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "pearl and platinum tiara" msgid_plural "pearl and platinum tiaras" -msgstr[0] "" +msgstr[0] "珍珠铂金王冠" #. ~ Description for {'str': 'pearl and platinum tiara'} #: data/json/items/armor/jewelry.json @@ -57178,7 +57377,7 @@ msgstr "一顶闪亮的镶有珍珠的铂金头饰。" #: data/json/items/armor/jewelry.json msgid "garnet and gold tiara" msgid_plural "garnet and gold tiaras" -msgstr[0] "" +msgstr[0] "石榴石金王冠" #. ~ Description for {'str': 'garnet and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57188,7 +57387,7 @@ msgstr "一顶闪亮的镶有石榴石的金头饰。" #: data/json/items/armor/jewelry.json msgid "diamond and gold tiara" msgid_plural "diamond and gold tiaras" -msgstr[0] "" +msgstr[0] "钻石金王冠" #. ~ Description for {'str': 'diamond and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57198,7 +57397,7 @@ msgstr "一顶闪亮的镶有钻石的金头饰。" #: data/json/items/armor/jewelry.json msgid "amethyst and gold tiara" msgid_plural "amethyst and gold tiaras" -msgstr[0] "" +msgstr[0] "紫水晶金王冠" #. ~ Description for {'str': 'amethyst and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57208,7 +57407,7 @@ msgstr "一顶闪亮的镶有紫水晶的金头饰。" #: data/json/items/armor/jewelry.json msgid "aquamarine and gold tiara" msgid_plural "aquamarine and gold tiaras" -msgstr[0] "" +msgstr[0] "海蓝宝石金王冠" #. ~ Description for {'str': 'aquamarine and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57218,7 +57417,7 @@ msgstr "一顶闪亮的镶有海蓝宝石的金头饰。" #: data/json/items/armor/jewelry.json msgid "emerald and gold tiara" msgid_plural "emerald and gold tiaras" -msgstr[0] "" +msgstr[0] "祖母绿金王冠" #. ~ Description for {'str': 'emerald and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57228,7 +57427,7 @@ msgstr "一顶闪亮的镶有祖母绿的金头饰。" #: data/json/items/armor/jewelry.json msgid "alexandrite and gold tiara" msgid_plural "alexandrite and gold tiaras" -msgstr[0] "" +msgstr[0] "紫翠玉金王冠" #. ~ Description for {'str': 'alexandrite and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57238,7 +57437,7 @@ msgstr "一顶闪亮的镶有紫翠玉的金头饰。" #: data/json/items/armor/jewelry.json msgid "ruby and gold tiara" msgid_plural "ruby and gold tiaras" -msgstr[0] "" +msgstr[0] "红宝石金王冠" #. ~ Description for {'str': 'ruby and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57248,7 +57447,7 @@ msgstr "一顶闪亮的镶有红宝石的金头饰。" #: data/json/items/armor/jewelry.json msgid "peridot and gold tiara" msgid_plural "peridot and gold tiaras" -msgstr[0] "" +msgstr[0] "橄榄石金王冠" #. ~ Description for {'str': 'peridot and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57258,7 +57457,7 @@ msgstr "一顶闪亮的镶有橄榄石的金头饰。" #: data/json/items/armor/jewelry.json msgid "sapphire and gold tiara" msgid_plural "sapphire and gold tiaras" -msgstr[0] "" +msgstr[0] "蓝宝石金王冠" #. ~ Description for {'str': 'sapphire and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57268,7 +57467,7 @@ msgstr "一顶闪亮的镶有蓝宝石的金头饰。" #: data/json/items/armor/jewelry.json msgid "tourmaline and gold tiara" msgid_plural "tourmaline and gold tiaras" -msgstr[0] "" +msgstr[0] "电气石金王冠" #. ~ Description for {'str': 'tourmaline and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57278,7 +57477,7 @@ msgstr "一顶闪亮的镶有电气石的金头饰。" #: data/json/items/armor/jewelry.json msgid "citrine and gold tiara" msgid_plural "citrine and gold tiaras" -msgstr[0] "" +msgstr[0] "黄水晶金王冠" #. ~ Description for {'str': 'citrine and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57288,7 +57487,7 @@ msgstr "一顶闪亮的镶有黄水晶的金头饰。" #: data/json/items/armor/jewelry.json msgid "blue topaz and gold tiara" msgid_plural "blue topaz and gold tiaras" -msgstr[0] "" +msgstr[0] "蓝黄玉金王冠" #. ~ Description for {'str': 'blue topaz and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57298,7 +57497,7 @@ msgstr "一顶闪亮的镶有蓝黄玉的金头饰。" #: data/json/items/armor/jewelry.json msgid "opal and gold tiara" msgid_plural "opal and gold tiaras" -msgstr[0] "" +msgstr[0] "蛋白石金王冠" #. ~ Description for {'str': 'opal and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57308,7 +57507,7 @@ msgstr "一顶闪亮的镶有蛋白石的金头饰。" #: data/json/items/armor/jewelry.json msgid "pearl and gold tiara" msgid_plural "pearl and gold tiaras" -msgstr[0] "" +msgstr[0] "珍珠金王冠" #. ~ Description for {'str': 'pearl and gold tiara'} #: data/json/items/armor/jewelry.json @@ -57318,7 +57517,7 @@ msgstr "一顶闪亮的镶有珍珠的金头饰。" #: data/json/items/armor/jewelry.json msgid "garnet and silver tiara" msgid_plural "garnet and silver tiaras" -msgstr[0] "" +msgstr[0] "石榴石银王冠" #. ~ Description for {'str': 'garnet and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57328,7 +57527,7 @@ msgstr "一顶闪亮的镶有石榴石的银头饰。" #: data/json/items/armor/jewelry.json msgid "diamond and silver tiara" msgid_plural "diamond and silver tiaras" -msgstr[0] "" +msgstr[0] "钻石银王冠" #. ~ Description for {'str': 'diamond and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57338,7 +57537,7 @@ msgstr "一顶闪亮的镶有钻石的银头饰。" #: data/json/items/armor/jewelry.json msgid "amethyst and silver tiara" msgid_plural "amethyst and silver tiaras" -msgstr[0] "" +msgstr[0] "紫水晶银王冠" #. ~ Description for {'str': 'amethyst and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57348,7 +57547,7 @@ msgstr "一顶闪亮的镶有紫水晶的银头饰。" #: data/json/items/armor/jewelry.json msgid "aquamarine and silver tiara" msgid_plural "aquamarine and silver tiaras" -msgstr[0] "" +msgstr[0] "海蓝宝石银王冠" #. ~ Description for {'str': 'aquamarine and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57358,7 +57557,7 @@ msgstr "一顶闪亮的镶有海蓝宝石的银头饰。" #: data/json/items/armor/jewelry.json msgid "emerald and silver tiara" msgid_plural "emerald and silver tiaras" -msgstr[0] "" +msgstr[0] "祖母绿银王冠" #. ~ Description for {'str': 'emerald and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57368,7 +57567,7 @@ msgstr "一顶闪亮的镶有祖母绿的银头饰。" #: data/json/items/armor/jewelry.json msgid "alexandrite and silver tiara" msgid_plural "alexandrite and silver tiaras" -msgstr[0] "" +msgstr[0] "紫翠玉银王冠" #. ~ Description for {'str': 'alexandrite and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57378,7 +57577,7 @@ msgstr "一顶闪亮的镶有紫翠玉的银头饰。" #: data/json/items/armor/jewelry.json msgid "ruby and silver tiara" msgid_plural "ruby and silver tiaras" -msgstr[0] "" +msgstr[0] "红宝石银王冠" #. ~ Description for {'str': 'ruby and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57388,7 +57587,7 @@ msgstr "一顶闪亮的镶有红宝石的银头饰。" #: data/json/items/armor/jewelry.json msgid "peridot and silver tiara" msgid_plural "peridot and silver tiaras" -msgstr[0] "" +msgstr[0] "橄榄石银王冠" #. ~ Description for {'str': 'peridot and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57398,7 +57597,7 @@ msgstr "一顶闪亮的镶有橄榄石的银头饰。" #: data/json/items/armor/jewelry.json msgid "sapphire and silver tiara" msgid_plural "sapphire and silver tiaras" -msgstr[0] "" +msgstr[0] "蓝宝石银王冠" #. ~ Description for {'str': 'sapphire and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57408,7 +57607,7 @@ msgstr "一顶闪亮的镶有蓝宝石的银头饰。" #: data/json/items/armor/jewelry.json msgid "tourmaline and silver tiara" msgid_plural "tourmaline and silver tiaras" -msgstr[0] "" +msgstr[0] "电气石银王冠" #. ~ Description for {'str': 'tourmaline and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57418,7 +57617,7 @@ msgstr "一顶闪亮的镶有电气石的银头饰。" #: data/json/items/armor/jewelry.json msgid "citrine and silver tiara" msgid_plural "citrine and silver tiaras" -msgstr[0] "" +msgstr[0] "黄水晶银王冠" #. ~ Description for {'str': 'citrine and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57428,7 +57627,7 @@ msgstr "一顶闪亮的镶有黄水晶的银头饰。" #: data/json/items/armor/jewelry.json msgid "blue topaz and silver tiara" msgid_plural "blue topaz and silver tiaras" -msgstr[0] "" +msgstr[0] "蓝黄玉银王冠" #. ~ Description for {'str': 'blue topaz and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57438,7 +57637,7 @@ msgstr "一顶闪亮的镶有蓝黄玉的银头饰。" #: data/json/items/armor/jewelry.json msgid "opal and silver tiara" msgid_plural "opal and silver tiaras" -msgstr[0] "" +msgstr[0] "蛋白石银王冠" #. ~ Description for {'str': 'opal and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57448,7 +57647,7 @@ msgstr "一顶闪亮的镶有蛋白石的银头饰。" #: data/json/items/armor/jewelry.json msgid "pearl and silver tiara" msgid_plural "pearl and silver tiaras" -msgstr[0] "" +msgstr[0] "珍珠银王冠" #. ~ Description for {'str': 'pearl and silver tiara'} #: data/json/items/armor/jewelry.json @@ -57855,7 +58054,7 @@ msgstr "一件有沉重毛皮內襯的長褲。" #: data/json/items/armor/legs_clothes.json msgid "faux fur pants" msgid_plural "faux fur pants" -msgstr[0] "" +msgstr[0] "人造毛皮长裤" #. ~ Description for {'str_sp': 'faux fur pants'} #: data/json/items/armor/legs_clothes.json @@ -58319,12 +58518,12 @@ msgstr "一塊塑料布, 上面有幾個索環供繩索固定。簡易的擋雨 #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "medium quadruped armor" msgid_plural "medium quadruped armors" -msgstr[0] "" +msgstr[0] "中型兽甲" #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "Kevlar-lined medium quadruped peto" msgid_plural "Kevlar-lined medium quadruped petos" -msgstr[0] "" +msgstr[0] "凯夫拉内衬中型兽甲" #. ~ Description for {'str': 'Kevlar-lined medium quadruped peto'} #: data/json/items/armor/pets_medium_quadruped_armor.json @@ -58337,7 +58536,7 @@ msgstr "一套由棉布、皮革和厚厚的凯夫拉内衬制成的沉重的床 #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "biosilicified chitin medium quadruped armor" msgid_plural "biosilicified chitin medium quadruped armors" -msgstr[0] "" +msgstr[0] "中型硅化甲壳兽甲" #. ~ Description for {'str': 'biosilicified chitin medium quadruped armor'} #: data/json/items/armor/pets_medium_quadruped_armor.json @@ -58351,7 +58550,7 @@ msgstr "" #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "chitin medium quadruped armor" msgid_plural "chitin medium quadruped armors" -msgstr[0] "" +msgstr[0] "中型甲壳兽甲" #. ~ Description for {'str': 'chitin medium quadruped armor'} #: data/json/items/armor/pets_medium_quadruped_armor.json @@ -58364,7 +58563,7 @@ msgstr "" #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "chainmail medium quadruped armor" msgid_plural "chainmail medium quadruped armors" -msgstr[0] "" +msgstr[0] "中型兽用链甲" #. ~ Description for {'str': 'chainmail medium quadruped armor'} #: data/json/items/armor/pets_medium_quadruped_armor.json @@ -58376,7 +58575,7 @@ msgstr "一套厚厚的铁环链甲,专门为保护中型四足动物打造。 #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "boiled leather medium quadruped barding with caprison" msgid_plural "boiled leather medium quadruped bardings with caprison" -msgstr[0] "" +msgstr[0] "中型华丽皮革兽铠" #. ~ Description for {'str': 'boiled leather medium quadruped barding with #. caprison', 'str_pl': 'boiled leather medium quadruped bardings with @@ -58454,7 +58653,7 @@ msgstr "" #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "boiled leather medium quadruped barding with bones" msgid_plural "boiled leather medium quadruped bardings with bones" -msgstr[0] "" +msgstr[0] "中型骨钉皮革兽铠" #. ~ Description for {'str': 'boiled leather medium quadruped barding with #. bones', 'str_pl': 'boiled leather medium quadruped bardings with bones'} @@ -58468,7 +58667,7 @@ msgstr "一套鞣制皮革制成的兽铠,上面附加了许多装饰性的骨 #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "medium quadruped rain sheet" msgid_plural "medium quadruped rain sheets" -msgstr[0] "" +msgstr[0] "中型兽用雨披" #. ~ Description for {'str': 'medium quadruped rain sheet'} #: data/json/items/armor/pets_medium_quadruped_armor.json @@ -58481,7 +58680,7 @@ msgstr "一层薄薄的能覆盖动物全身的塑料布,能够防护酸雨和 #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "superalloy medium quadruped armor" msgid_plural "superalloy medium quadruped armors" -msgstr[0] "" +msgstr[0] "中型超合金兽甲" #. ~ Description for {'str': 'superalloy medium quadruped armor'} #: data/json/items/armor/pets_medium_quadruped_armor.json @@ -58495,7 +58694,7 @@ msgstr "" #: data/json/items/armor/pets_medium_quadruped_armor.json msgid "pair of saddle bags" msgid_plural "pairs of saddle bags" -msgstr[0] "" +msgstr[0] "鞍袋" #. ~ Description for {'str': 'pair of saddle bags', 'str_pl': 'pairs of saddle #. bags'} @@ -58508,12 +58707,12 @@ msgstr "一对有盖的袋子横放在鞍后面的中型四足动物背上。" #: data/json/items/armor/pets_small_quadruped_armor.json msgid "small quadruped armor" msgid_plural "small quadruped armors" -msgstr[0] "" +msgstr[0] "小型兽甲" #: data/json/items/armor/pets_small_quadruped_armor.json msgid "Kevlar-lined small quadruped peto" msgid_plural "Kevlar-lined small quadruped petos" -msgstr[0] "" +msgstr[0] "凯夫拉内衬小型兽甲" #. ~ Description for {'str': 'Kevlar-lined small quadruped peto'} #: data/json/items/armor/pets_small_quadruped_armor.json @@ -58526,7 +58725,7 @@ msgstr "一套由棉布、皮革和厚厚的凯夫拉内衬制成的沉重的床 #: data/json/items/armor/pets_small_quadruped_armor.json msgid "biosilicified chitin small quadruped armor" msgid_plural "biosilicified chitin small quadruped armors" -msgstr[0] "" +msgstr[0] "小型硅化甲壳兽甲" #. ~ Description for {'str': 'biosilicified chitin small quadruped armor'} #: data/json/items/armor/pets_small_quadruped_armor.json @@ -58540,7 +58739,7 @@ msgstr "" #: data/json/items/armor/pets_small_quadruped_armor.json msgid "chitin small quadruped armor" msgid_plural "chitin small quadruped armors" -msgstr[0] "" +msgstr[0] "小型甲壳兽甲" #. ~ Description for {'str': 'chitin small quadruped armor'} #: data/json/items/armor/pets_small_quadruped_armor.json @@ -58553,7 +58752,7 @@ msgstr "" #: data/json/items/armor/pets_small_quadruped_armor.json msgid "chainmail small quadruped armor" msgid_plural "chainmail small quadruped armors" -msgstr[0] "" +msgstr[0] "小型兽用链甲" #. ~ Description for {'str': 'chainmail small quadruped armor'} #: data/json/items/armor/pets_small_quadruped_armor.json @@ -58566,7 +58765,7 @@ msgstr "一套厚厚的铁环链甲,专门为保护小型四足动物打造。 #: data/json/items/armor/pets_small_quadruped_armor.json msgid "boiled leather small quadruped barding with caprison" msgid_plural "boiled leather small quadruped bardings with caprison" -msgstr[0] "" +msgstr[0] "小型华丽皮革兽铠" #. ~ Description for {'str': 'boiled leather small quadruped barding with #. caprison', 'str_pl': 'boiled leather small quadruped bardings with @@ -58582,7 +58781,7 @@ msgstr "" #: data/json/items/armor/pets_small_quadruped_armor.json msgid "boiled leather small quadruped barding with bones" msgid_plural "boiled leather small quadruped bardings with bones" -msgstr[0] "" +msgstr[0] "小型骨钉皮革兽铠" #. ~ Description for {'str': 'boiled leather small quadruped barding with #. bones', 'str_pl': 'boiled leather small quadruped bardings with bones'} @@ -58596,7 +58795,7 @@ msgstr "一套鞣制皮革制成的兽铠,上面附加了许多装饰性的骨 #: data/json/items/armor/pets_small_quadruped_armor.json msgid "small quadruped rain sheet" msgid_plural "small quadruped rain sheets" -msgstr[0] "" +msgstr[0] "小型兽用雨披" #. ~ Description for {'str': 'small quadruped rain sheet'} #: data/json/items/armor/pets_small_quadruped_armor.json @@ -58609,7 +58808,7 @@ msgstr "一层薄薄的能覆盖动物全身的塑料布,能够防护酸雨和 #: data/json/items/armor/pets_small_quadruped_armor.json msgid "superalloy small quadruped armor" msgid_plural "superalloy small quadruped armors" -msgstr[0] "" +msgstr[0] "小型超合金兽甲" #. ~ Description for {'str': 'superalloy small quadruped armor'} #: data/json/items/armor/pets_small_quadruped_armor.json @@ -58623,7 +58822,7 @@ msgstr "" #: data/json/items/armor/pets_small_quadruped_armor.json msgid "pair of saddle bags for small quadruped" msgid_plural "pairs of saddle bags for small quadruped" -msgstr[0] "" +msgstr[0] "小型鞍袋" #. ~ Description for {'str': 'pair of saddle bags for small quadruped', #. 'str_pl': 'pairs of saddle bags for small quadruped'} @@ -58919,7 +59118,7 @@ msgstr "一个与军用外骨骼配套使用的携行系统。" #: data/json/items/armor/power_armor.json msgid "power armor back holster" msgid_plural "power armor back holsters" -msgstr[0] "" +msgstr[0] "动力装甲枪套(背)" #. ~ Description for {'str': 'power armor back holster'} #: data/json/items/armor/power_armor.json @@ -58933,7 +59132,7 @@ msgstr "一种重型枪套,使用夹子和导轨接口的组合来舒适地固 #: data/json/items/armor/power_armor.json msgid "power armor holster" msgid_plural "power armor holsters" -msgstr[0] "" +msgstr[0] "动力装甲枪套" #. ~ Description for {'str': 'power armor holster'} #: data/json/items/armor/power_armor.json @@ -58947,7 +59146,7 @@ msgstr "一种重型枪套,使用密封件和导轨接口的组合来舒适地 #: data/json/items/armor/power_armor.json msgid "power armor chest rig" msgid_plural "power armor chest rigs" -msgstr[0] "" +msgstr[0] "动力装甲弹匣包(胸)" #. ~ Description for {'str': 'power armor chest rig'} #: data/json/items/armor/power_armor.json @@ -58960,7 +59159,7 @@ msgstr "一组弹匣包,可携带三个弹匣。设计用于与军用外骨骼 #: data/json/items/armor/power_armor.json msgid "power armor back scabbard" msgid_plural "power armor back scabbards" -msgstr[0] "" +msgstr[0] "动力装甲刀鞘(背)" #. ~ Use action holster_prompt for {'str': 'power armor back scabbard'}. #. ~ Use action holster_prompt for {'str': 'baldric'}. @@ -58983,7 +59182,7 @@ msgstr "一套夹具和配件,设计用于容纳各种大型刀片武器。设 #: data/json/items/armor/power_armor.json msgid "power armor scabbard" msgid_plural "power armor scabbards" -msgstr[0] "" +msgstr[0] "动力装甲剑鞘" #. ~ Description for {'str': 'power armor scabbard'} #: data/json/items/armor/power_armor.json @@ -58996,7 +59195,7 @@ msgstr "一套夹具和配件,用于容纳各种剑和类似武器。设计用 #: data/json/items/armor/power_armor.json msgid "power armor sheath" msgid_plural "power armor sheaths" -msgstr[0] "" +msgstr[0] "动力装甲刀鞘" #. ~ Use action holster_prompt for {'str': 'power armor sheath'}. #. ~ Use action holster_prompt for {'str': 'ankle sheath'}. @@ -59050,7 +59249,7 @@ msgstr "一種中東的傳統頭巾。它能以各種方式保護頭部與嘴巴 #: data/json/items/armor/scarfs.json msgid "cyan scarf" msgid_plural "cyan scarfs" -msgstr[0] "" +msgstr[0] "青色领巾" #. ~ Description for {'str': 'cyan scarf'} #: data/json/items/armor/scarfs.json @@ -59062,7 +59261,7 @@ msgstr "一条马洛斯之声成员佩戴的造型朴素的青色领巾。据说 #: data/json/items/armor/sheath.json msgid "axe ring holster" msgid_plural "axe ring holsters" -msgstr[0] "" +msgstr[0] "斧套" #. ~ Use action holster_prompt for {'str': 'axe ring holster'}. #: data/json/items/armor/sheath.json @@ -59399,7 +59598,7 @@ msgstr "你準備好沿著鐵軌旅行了。這東西也被稱作流浪漢的鋪 #: data/json/items/armor/storage.json msgid "box backpack" msgid_plural "box backpacks" -msgstr[0] "" +msgstr[0] "木箱背包" #. ~ Description for {'str': 'box backpack'} #: data/json/items/armor/storage.json @@ -59419,7 +59618,7 @@ msgstr "用途是裝錢, 放文件, 或是走私物品。" #: data/json/items/armor/storage.json msgid "violin case" msgid_plural "violin cases" -msgstr[0] "" +msgstr[0] "小提琴盒" #. ~ Description for {'str': 'violin case'} #: data/json/items/armor/storage.json @@ -59509,7 +59708,7 @@ msgstr "一個用於高爾夫球的高大帆布袋, 帶有折疊式支架, 甚 #: data/json/items/armor/storage.json msgid "hide bag" msgid_plural "hide bags" -msgstr[0] "" +msgstr[0] "生皮袋" #. ~ Description for {'str': 'hide bag'} #: data/json/items/armor/storage.json @@ -59521,7 +59720,7 @@ msgstr "用動物的生皮革快速製作成的臨時儲物袋。它仍會腐敗 #: data/json/items/armor/storage.json msgid "tainted hide bag" msgid_plural "tainted hide bags" -msgstr[0] "" +msgstr[0] "感染生皮袋" #. ~ Description for {'str': 'tainted hide bag'} #: data/json/items/armor/storage.json @@ -59533,7 +59732,7 @@ msgstr "用怪物的生皮革快速製作成的臨時儲物袋。它仍會腐敗 #: data/json/items/armor/storage.json msgid "H&K operational briefcase (empty)" msgid_plural "H&K operational briefcases (empty)" -msgstr[0] "" +msgstr[0] "H&K 特工手提箱(空)" #. ~ Description for {'str': 'H&K operational briefcase (empty)', 'str_pl': #. 'H&K operational briefcases (empty)'} @@ -59739,7 +59938,7 @@ msgstr "一個中型的旅行箱, 主要用於運送旅行期間的衣服或其 #: data/json/items/armor/storage.json msgid "survivor hiking backpack" msgid_plural "survivor hiking backpacks" -msgstr[0] "" +msgstr[0] "幸存者登山包" #. ~ Description for {'str': 'survivor hiking backpack'} #: data/json/items/armor/storage.json @@ -59950,7 +60149,7 @@ msgstr "一件累贅的羊毛西裝繡有漂亮的圖案。它看起來就像全 #: data/json/items/armor/suits_clothes.json msgid "zentai" msgid_plural "zentais" -msgstr[0] "" +msgstr[0] "全包紧身衣" #. ~ Description for {'str': 'zentai'} #: data/json/items/armor/suits_clothes.json @@ -60197,7 +60396,7 @@ msgstr "一套自制的完整链甲套装,包含头巾。胸甲、护臂、护 #: data/json/items/armor/suits_protection.json msgid "faraday chainmail suit" msgid_plural "faraday chainmail suits" -msgstr[0] "" +msgstr[0] "法拉第锁环服" #. ~ Description for {'str': 'faraday chainmail suit'} #: data/json/items/armor/suits_protection.json @@ -60332,7 +60531,7 @@ msgstr "一套緊密貼身的全身裝束, 由輕量的諾梅克斯阻燃纖維 #: data/json/items/armor/suits_protection.json msgid "Hub 01 environmental suit" msgid_plural "Hub 01 environmental suits" -msgstr[0] "" +msgstr[0] "HUB 01 环护服" #. ~ Description for {'str': 'Hub 01 environmental suit'} #: data/json/items/armor/suits_protection.json @@ -60713,7 +60912,7 @@ msgstr "一件裝甲外套, 由厚實的皮革與金屬板製成。有點累贅, #: data/json/items/armor/torso_armor.json msgid "occult bone armor" msgid_plural "occult bone armors" -msgstr[0] "" +msgstr[0] "邪异骨甲" #. ~ Description for {'str': 'occult bone armor'} #: data/json/items/armor/torso_armor.json @@ -60727,7 +60926,7 @@ msgstr "" #: data/json/items/armor/torso_armor.json msgid "lamé (foil)" msgid_plural "lamés (foil)" -msgstr[0] "" +msgstr[0] "导电服(花剑)" #. ~ Description for {'str': 'lamé (foil)', 'str_pl': 'lamés (foil)'} #: data/json/items/armor/torso_armor.json @@ -60740,7 +60939,7 @@ msgstr "一件轻薄的导电背心,背部有拉链,用于在击剑时电子 #: data/json/items/armor/torso_armor.json msgid "lamé (saber)" msgid_plural "lamés (saber)" -msgstr[0] "" +msgstr[0] "导电服(佩剑)" #. ~ Description for {'str': 'lamé (saber)', 'str_pl': 'lamés (saber)'} #: data/json/items/armor/torso_armor.json @@ -60798,7 +60997,7 @@ msgstr "一套供越野自行車與摩托車騎士使用的護具。" #: data/json/items/armor/torso_armor.json msgid "underarm protector" msgid_plural "underarm protectors" -msgstr[0] "" +msgstr[0] "腋下护甲" #. ~ Description for {'str': 'underarm protector'} #: data/json/items/armor/torso_armor.json @@ -60810,7 +61009,7 @@ msgstr "一件结实的棉质胸甲,能在击剑时保护大部分躯干、肩 #: data/json/items/armor/torso_armor.json msgid "plastic chest protector" msgid_plural "plastic chest protectors" -msgstr[0] "" +msgstr[0] "塑料胸甲" #. ~ Description for {'str': 'plastic chest protector'} #: data/json/items/armor/torso_armor.json @@ -61029,7 +61228,7 @@ msgstr "一件由厚实布料作成的排球球衣,上头印有大洗鸭子队 #: data/json/items/armor/torso_clothes.json msgid "leotard" msgid_plural "leotard" -msgstr[0] "" +msgstr[0] "紧身连衣裤" #. ~ Description for {'str_sp': 'leotard'} #: data/json/items/armor/torso_clothes.json @@ -61573,7 +61772,7 @@ msgstr "為女性設計的內衣。在末日的時候保持著你的端莊。" #: data/json/items/armor/undergarment.json msgid "thermal shirt" msgid_plural "thermal shirts" -msgstr[0] "" +msgstr[0] "保暖衬衫" #. ~ Description for {'str': 'thermal shirt'} #: data/json/items/armor/undergarment.json @@ -61654,7 +61853,7 @@ msgstr "一個簡單的白色汗衫。穿在你其他衣服的內層, 能夠起 #: data/json/items/armor/undergarment.json msgid "unitard" msgid_plural "unitards" -msgstr[0] "" +msgstr[0] "全身紧身衣" #. ~ Description for {'str': 'unitard'} #: data/json/items/armor/undergarment.json @@ -61668,7 +61867,7 @@ msgstr "" #: data/json/items/book/archery.json msgid "Lessons for the Novice Bowhunter" msgid_plural "copies of Lessons for the Novice Bowhunter" -msgstr[0] "" +msgstr[0] "弓箭手入门教程" #. ~ Description for {'str': 'Lessons for the Novice Bowhunter', 'str_pl': #. 'copies of Lessons for the Novice Bowhunter'} @@ -61681,7 +61880,7 @@ msgstr "這個沉重的平裝書包含新手利用弓和弩進行狩獵所需要 #: data/json/items/book/archery.json msgid "Archery for Kids" msgid_plural "issues of Archery for Kids" -msgstr[0] "" +msgstr[0] "少儿弓术入门" #. ~ Description for {'str': 'Archery for Kids', 'str_pl': 'issues of Archery #. for Kids'} @@ -61695,7 +61894,7 @@ msgstr "你有辦法將箭射中紅心嗎? 這並不簡單, 但如果你知道 #: data/json/items/book/archery.json msgid "Zen and the Art of Archery" msgid_plural "copies of Zen and the Art of Archery" -msgstr[0] "" +msgstr[0] "弓与禅" #. ~ Description for {'str': 'Zen and the Art of Archery', 'str_pl': 'copies #. of Zen and the Art of Archery'} @@ -61720,7 +61919,7 @@ msgstr "通常這種亮面雜誌充滿著無意義的汽車廣告, 但是還是 #: data/json/items/book/barter.json msgid "How to Succeed in Business" msgid_plural "copies of How to Succeed in Business" -msgstr[0] "" +msgstr[0] "商业秘诀" #. ~ Description for {'str': 'How to Succeed in Business', 'str_pl': 'copies #. of How to Succeed in Business'} @@ -61731,7 +61930,7 @@ msgstr "假如你想要在購物時拿到好價錢的話可以參考看看。" #: data/json/items/book/barter.json msgid "Advanced Economics" msgid_plural "copies of Advanced Economics" -msgstr[0] "" +msgstr[0] "高级经济学" #. ~ Description for {'str': 'Advanced Economics', 'str_pl': 'copies of #. Advanced Economics'} @@ -61742,7 +61941,7 @@ msgstr "一本有關經濟學的大學課本。" #: data/json/items/book/bashing.json msgid "Batter Up!" msgid_plural "issues of Batter Up!" -msgstr[0] "" +msgstr[0] "完美击球杂志" #. ~ Description for {'str': 'Batter Up!', 'str_pl': 'issues of Batter Up!'} #: data/json/items/book/bashing.json @@ -61768,7 +61967,7 @@ msgstr "教導使用棍棒與甩棍自衛的知識性書籍。主要是針對執 #: data/json/items/book/bloat.json msgid "Mycenacean Hymns" msgid_plural "copies of Mycenacean Hymns" -msgstr[0] "" +msgstr[0] "迈锡尼的赞美诗" #. ~ Description for {'str': 'Mycenacean Hymns', 'str_pl': 'copies of #. Mycenacean Hymns'} @@ -61781,7 +61980,7 @@ msgstr "羊皮纸书,包含了对马洛斯信仰至关重要的赞美诗。这 #: data/json/items/book/bloat.json msgid "Eastern Orthodox Bible" msgid_plural "copies of Eastern Orthodox Bible" -msgstr[0] "" +msgstr[0] "东正教圣经" #. ~ Description for {'str': 'Eastern Orthodox Bible', 'str_pl': 'copies of #. Eastern Orthodox Bible'} @@ -61792,7 +61991,7 @@ msgstr "東正教的聖經英譯本。" #: data/json/items/book/bloat.json msgid "Gideon Bible" msgid_plural "copies of Gideon Bible" -msgstr[0] "" +msgstr[0] "基甸版圣经" #. ~ Description for {'str': 'Gideon Bible', 'str_pl': 'copies of Gideon #. Bible'} @@ -61816,7 +62015,7 @@ msgstr "錫克教的宗教核心文本。" #: data/json/items/book/bloat.json msgid "Hadith" msgid_plural "copies of Hadith" -msgstr[0] "" +msgstr[0] "圣训" #. ~ Description for {'str': 'Hadith', 'str_pl': 'copies of Hadith'} #: data/json/items/book/bloat.json @@ -61881,7 +62080,7 @@ msgstr "一本書, 描述了以飛天麵條怪物為主要信仰的教會。它 #: data/json/items/book/bloat.json msgid "Quran" msgid_plural "copies of Quran" -msgstr[0] "" +msgstr[0] "古兰经" #. ~ Description for {'str': 'Quran', 'str_pl': 'copies of Quran'} #: data/json/items/book/bloat.json @@ -61931,7 +62130,7 @@ msgstr "一本佛陀諸弟子與佛陀間對話的合輯。" #: data/json/items/book/bloat.json msgid "Talmud" msgid_plural "copies of Talmud" -msgstr[0] "" +msgstr[0] "塔木德" #. ~ Description for {'str': 'Talmud', 'str_pl': 'copies of Talmud'} #: data/json/items/book/bloat.json @@ -61943,7 +62142,7 @@ msgstr "一個拉比猶太教的核心文本, 猶太法典闡述了在希伯來 #: data/json/items/book/bloat.json msgid "Tanakh" msgid_plural "copies of Tanakh" -msgstr[0] "" +msgstr[0] "旧约圣经" #. ~ Description for {'str': 'Tanakh', 'str_pl': 'copies of Tanakh'} #: data/json/items/book/bloat.json @@ -61954,7 +62153,7 @@ msgstr "一卷書, 包含了猶太聖經的所有章節。" #: data/json/items/book/bloat.json msgid "The Tripitaka" msgid_plural "copies of The Tripitaka" -msgstr[0] "" +msgstr[0] "大藏经" #. ~ Description for {'str': 'The Tripitaka', 'str_pl': 'copies of The #. Tripitaka'} @@ -61993,7 +62192,7 @@ msgstr "一個包含所有四個吠陀經的合輯本, 這是印度教最古老 #: data/json/items/book/bloat.json msgid "The Satanic Bible" msgid_plural "copies of The Satanic Bible" -msgstr[0] "" +msgstr[0] "撒旦圣经" #. ~ Description for {'str': 'The Satanic Bible', 'str_pl': 'copies of The #. Satanic Bible'} @@ -62019,7 +62218,7 @@ msgstr "一本翻譯成英文的古北歐語詩集。詩集包含了有關歐丁 #: data/json/items/book/bloat.json msgid "priest's diary" msgid_plural "priests' diaries" -msgstr[0] "" +msgstr[0] "牧师日记" #. ~ Description for {'str': "priest's diary", 'str_pl': "priests' diaries"} #: data/json/items/book/bloat.json @@ -62029,7 +62228,7 @@ msgstr "一本寫滿拉丁文的小書。" #: data/json/items/book/bloat.json msgid "The Hitchhiker's Guide to the Cataclysm" msgid_plural "copies of The Hitchhiker's Guide to the Cataclysm" -msgstr[0] "" +msgstr[0] "大灾变漫游指南" #. ~ Description for {'str': "The Hitchhiker's Guide to the Cataclysm", #. 'str_pl': "copies of The Hitchhiker's Guide to the Cataclysm"} @@ -62042,7 +62241,7 @@ msgstr "封面上用易讀的字體寫著大大的 \"別慌\"。(此物品引用 #: data/json/items/book/bloat.json msgid "Murdered by the Grapevine" msgid_plural "copies of Murdered by the Grapevine" -msgstr[0] "" +msgstr[0] "被葡萄藤所谋杀" #. ~ Description for {'str': 'Murdered by the Grapevine', 'str_pl': 'copies of #. Murdered by the Grapevine'} @@ -62058,7 +62257,7 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Come Fly the Treacherous Skies" msgid_plural "copies of Come Fly the Treacherous Skies" -msgstr[0] "" +msgstr[0] "来飞过这险恶的天空" #. ~ Description for {'str': 'Come Fly the Treacherous Skies', 'str_pl': #. 'copies of Come Fly the Treacherous Skies'} @@ -62074,7 +62273,7 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Lies, Damn Lies, and Rocket Science" msgid_plural "copies of Lies, Damn Lies, and Rocket Science" -msgstr[0] "" +msgstr[0] "谎言,该死的谎言,以及火箭科学" #. ~ Description for {'str': 'Lies, Damn Lies, and Rocket Science', 'str_pl': #. 'copies of Lies, Damn Lies, and Rocket Science'} @@ -62090,7 +62289,7 @@ msgstr "" #: data/json/items/book/bloat.json msgid "Visions in Solitude" msgid_plural "copies of Visions in Solitude" -msgstr[0] "" +msgstr[0] "荒野胜景" #. ~ Description for {'str': 'Visions in Solitude', 'str_pl': 'copies of #. Visions in Solitude'} @@ -62101,7 +62300,7 @@ msgstr "一本冊子記載著一位死刑犯在牢裡看到的 \"景象\"。" #: data/json/items/book/bloat.json msgid "Zombie Survival Guide" msgid_plural "copies of Zombie Survival Guide" -msgstr[0] "" +msgstr[0] "丧尸生存指南" #. ~ Description for {'str': 'Zombie Survival Guide', 'str_pl': 'copies of #. Zombie Survival Guide'} @@ -62114,7 +62313,7 @@ msgstr "在目前這情形下, 這本書乍看起來很實用, 但是裡面充 #: data/json/items/book/computer.json msgid "SICP" msgid_plural "copies of SICP" -msgstr[0] "" +msgstr[0] "计算机程序的构造和解释" #. ~ Description for {'str': 'SICP', 'str_pl': 'copies of SICP'} #: data/json/items/book/computer.json @@ -62126,7 +62325,7 @@ msgstr "一本資訊課本, 全名為 \"電腦程式的構造和解釋\"。它 #: data/json/items/book/computer.json msgid "Computer Science 301" msgid_plural "copies of Computer Science 301" -msgstr[0] "" +msgstr[0] "计算机科学进阶" #. ~ Description for {'str': 'Computer Science 301', 'str_pl': 'copies of #. Computer Science 301'} @@ -62137,7 +62336,7 @@ msgstr "一本大學電腦科學的課本。" #: data/json/items/book/computer.json msgid "How to Browse the Web" msgid_plural "copies of How to Browse the Web" -msgstr[0] "" +msgstr[0] "如何浏览网页" #. ~ Description for {'str': 'How to Browse the Web', 'str_pl': 'copies of How #. to Browse the Web'} @@ -62148,7 +62347,7 @@ msgstr "一本非常基礎的電腦知識書籍。" #: data/json/items/book/computer.json msgid "Computer World" msgid_plural "issues of Computer World" -msgstr[0] "" +msgstr[0] "计算机世界杂志" #. ~ Description for {'str': 'Computer World', 'str_pl': 'issues of Computer #. World'} @@ -62160,7 +62359,7 @@ msgstr "一本全部關於電腦知識的雜誌, 包含了硬體與軟體。" #: data/json/items/book/computer.json msgid "Computer Science 101" msgid_plural "copies of Computer Science 101" -msgstr[0] "" +msgstr[0] "计算机科学基础" #. ~ Description for {'str': 'Computer Science 101', 'str_pl': 'copies of #. Computer Science 101'} @@ -62171,7 +62370,7 @@ msgstr "一本入門級的電腦課本。" #: data/json/items/book/computer.json msgid "Principles of Advanced Programming" msgid_plural "copies of Principles of Advanced Programming" -msgstr[0] "" +msgstr[0] "高级编程原理" #. ~ Description for {'str': 'Principles of Advanced Programming', 'str_pl': #. 'copies of Principles of Advanced Programming'} @@ -62184,7 +62383,7 @@ msgstr "一個沉重的教科書, 內容是進階水準的程式設計, 並且 #: data/json/items/book/cooking.json msgid "Advanced Physical Chemistry" msgid_plural "copies of Advanced Physical Chemistry" -msgstr[0] "" +msgstr[0] "大学化学" #. ~ Description for {'str': 'Advanced Physical Chemistry', 'str_pl': 'copies #. of Advanced Physical Chemistry'} @@ -62197,7 +62396,7 @@ msgstr "講述進階化學原理的大學教科書, 包含了有機和無機部 #: data/json/items/book/cooking.json msgid "The Homebrewer's Bible" msgid_plural "copies of The Homebrewer's Bible" -msgstr[0] "" +msgstr[0] "酿造者宝典" #. ~ Description for {'str': "The Homebrewer's Bible", 'str_pl': "copies of #. The Homebrewer's Bible"} @@ -62210,7 +62409,7 @@ msgstr "一本寫滿了簡單易懂配方和有用建議的私家釀酒指南, #: data/json/items/book/cooking.json msgid "Cooking on a Budget" msgid_plural "copies of Cooking on a Budget" -msgstr[0] "" +msgstr[0] "巧主妇烹饪大全" #. ~ Description for {'str': 'Cooking on a Budget', 'str_pl': 'copies of #. Cooking on a Budget'} @@ -62222,7 +62421,7 @@ msgstr "一本很好的書, 講解了許多配方與食物間的化學變化。" #: data/json/items/book/cooking.json msgid "To Serve Man" msgid_plural "copies of To Serve Man" -msgstr[0] "" +msgstr[0] "料理达人" #. ~ Description for {'str': 'To Serve Man', 'str_pl': 'copies of To Serve #. Man'} @@ -62235,7 +62434,7 @@ msgstr "" #: data/json/items/book/cooking.json msgid "Cucina Italiana" msgid_plural "copies of Cucina Italiana" -msgstr[0] "" +msgstr[0] "意大利厨艺" #. ~ Description for {'str': 'Cucina Italiana', 'str_pl': 'copies of Cucina #. Italiana'} @@ -62276,7 +62475,7 @@ msgstr "一本某人的家族烹飪食譜。裡面充滿了各種手寫筆記與 #: data/json/items/book/cooking.json msgid "Bon Appetit" msgid_plural "issues of Bon Appetit" -msgstr[0] "" +msgstr[0] "好胃口杂志" #. ~ Description for {'str': 'Bon Appetit', 'str_pl': 'issues of Bon Appetit'} #: data/json/items/book/cooking.json @@ -62287,7 +62486,7 @@ msgstr "提供各種令人胃口大開的食譜以及餐廳介紹。充滿了許 #: data/json/items/book/cooking.json msgid "Glamopolitan" msgid_plural "issues of Glamopolitan" -msgstr[0] "" +msgstr[0] "时尚丽人" #. ~ Description for {'str': 'Glamopolitan', 'str_pl': 'issues of #. Glamopolitan'} @@ -62314,7 +62513,7 @@ msgstr "一本关于鞣制的指南,详细介绍了从古至今的皮革鞣制 #: data/json/items/book/cooking.json msgid "PE050 \"Alpha\": Preliminary Report" msgid_plural "copies of PE050 \"Alpha\": Preliminary Report" -msgstr[0] "" +msgstr[0] "PE050 \"Alpha\":初步报告" #. ~ Description for {'str': 'PE050 "Alpha": Preliminary Report', 'str_pl': #. 'copies of PE050 "Alpha": Preliminary Report'} @@ -62342,7 +62541,7 @@ msgstr "該團隊日誌詳述了幾個品種的突變實驗, 著眼於從各種 #: data/json/items/book/cooking.json msgid "PE065 \"Chimera\": Best Practices" msgid_plural "copies of PE065 \"Chimera\": Best Practices" -msgstr[0] "" +msgstr[0] "PE065 \"Chimera\":最佳实践报告" #. ~ Description for {'str': 'PE065 "Chimera": Best Practices', 'str_pl': #. 'copies of PE065 "Chimera": Best Practices'} @@ -62415,7 +62614,7 @@ msgstr "該受損的團隊日誌 (故意? ) 缺少任何識別訊息, 但是仍 #: data/json/items/book/cooking.json msgid "PE023 \"Medical\": Application and Findings" msgid_plural "copies of PE023 \"Medical\": Application and Findings" -msgstr[0] "" +msgstr[0] "PE023 \"Medical\":应用及结果" #. ~ Description for {'str': 'PE023 "Medical": Application and Findings', #. 'str_pl': 'copies of PE023 "Medical": Application and Findings'} @@ -62428,7 +62627,7 @@ msgstr "这些尖端技术论文描述了一些全新的化学配方以及他们 #: data/json/items/book/cooking.json msgid "PE070 \"Raptor\": Proposal" msgid_plural "copies of PE070 \"Raptor\": Proposal" -msgstr[0] "" +msgstr[0] "PE070 \"Raptor\":提案" #. ~ Description for {'str': 'PE070 "Raptor": Proposal', 'str_pl': 'copies of #. PE070 "Raptor": Proposal'} @@ -62442,7 +62641,7 @@ msgstr "这捆文件是关于一个代号为\"PE065\"的高风险方案。各处 #: data/json/items/book/cooking.json msgid "Best Practices for Compound Delivery" msgid_plural "copies of Best Practices for Compound Delivery" -msgstr[0] "" +msgstr[0] "化合药物体内传递实例操作" #. ~ Description for {'str': 'Best Practices for Compound Delivery', 'str_pl': #. 'copies of Best Practices for Compound Delivery'} @@ -62460,7 +62659,7 @@ msgstr "" #: data/json/items/book/cooking.json msgid "CRC-Merck Handbook, 4th edition" msgid_plural "copies of CRC-Merck Handbook, 4th edition" -msgstr[0] "" +msgstr[0] "CRC化学和物理手册(附默克索引,第四版)" #. ~ Description for {'str': 'CRC-Merck Handbook, 4th edition', 'str_pl': #. 'copies of CRC-Merck Handbook, 4th edition'} @@ -62505,7 +62704,7 @@ msgstr "一本化學的大學課本。" #: data/json/items/book/cooking.json msgid "The Vinegar Maker's Handbook" msgid_plural "copies of Vinegar Maker's Handbook" -msgstr[0] "" +msgstr[0] "酿醋者手册" #. ~ Description for {'str': "The Vinegar Maker's Handbook", 'str_pl': "copies #. of Vinegar Maker's Handbook"} @@ -62519,7 +62718,7 @@ msgstr "这本书详细描述了酿醋的所有方法。你可能认为酿醋没 #: data/json/items/book/cooking.json msgid "Drink the Harvest" msgid_plural "copies of Drink the Harvest" -msgstr[0] "" +msgstr[0] "《畅饮丰年》影本" #. ~ Description for {'str': 'Drink the Harvest', 'str_pl': 'copies of Drink #. the Harvest'} @@ -62532,7 +62731,7 @@ msgstr "罐装食品不必再局限于果酱和腌菜。这本书提供了超多 #: data/json/items/book/cooking.json msgid "Offal Holiday Cooking" msgid_plural "copies of Offal Holiday Cooking" -msgstr[0] "" +msgstr[0] "内脏节日料理" #. ~ Description for {'str': 'Offal Holiday Cooking', 'str_pl': 'copies of #. Offal Holiday Cooking'} @@ -62545,7 +62744,7 @@ msgstr "《内脏节日料理》是一本关于节日料理食谱的书,伊芙 #: data/json/items/book/cooking.json msgid "Things to do with Milk" msgid_plural "copies of Things to do with Milk" -msgstr[0] "" +msgstr[0] "与牛奶有关的事" #. ~ Description for {'str': 'Things to do with Milk', 'str_pl': 'copies of #. Things to do with Milk'} @@ -62557,7 +62756,7 @@ msgstr "无论你想用牛奶做什么菜,你都能在这本书里找到配方 #: data/json/items/book/cooking.json msgid "Liver-Licious Recipes Your Kids Will Love" msgid_plural "copies of Liver-Licious Recipes" -msgstr[0] "" +msgstr[0] "宝宝最爱肝脏料理" #. ~ Description for {'str': 'Liver-Licious Recipes Your Kids Will Love', #. 'str_pl': 'copies of Liver-Licious Recipes'} @@ -62571,7 +62770,7 @@ msgstr "这本食谱是由肝脏料理狂热分子塔姆辛·贝克雷格编著 #: data/json/items/book/cooking.json msgid "Dainty Dishes Fit for a King" msgid_plural "copies of Dainty Dishes" -msgstr[0] "" +msgstr[0] "精美皇家料理" #. ~ Description for {'str': 'Dainty Dishes Fit for a King', 'str_pl': 'copies #. of Dainty Dishes'} @@ -62585,7 +62784,7 @@ msgstr "这本书列举了许多花哨的菜谱,书页上用钢笔风格绘制 #: data/json/items/book/cooking.json msgid "Eat Your Way to a Fit Physique" msgid_plural "copies of Eat Your Way" -msgstr[0] "" +msgstr[0] "吃出好身材" #. ~ Description for {'str': 'Eat Your Way to a Fit Physique', 'str_pl': #. 'copies of Eat Your Way'} @@ -62598,7 +62797,7 @@ msgstr "这本参考书的内容和它的标题一样可疑,而更糟糕的是 #: data/json/items/book/cooking.json msgid "Food Fashions for Young Moderns" msgid_plural "copies of Food Fashions" -msgstr[0] "" +msgstr[0] "年轻新食尚" #. ~ Description for {'str': 'Food Fashions for Young Moderns', 'str_pl': #. 'copies of Food Fashions'} @@ -62613,7 +62812,7 @@ msgstr "一本自称是为追求\"大胆且复杂的味觉体验\"的人所编 #: data/json/items/book/cooking.json msgid "Winemaking for Beginners" msgid_plural "copies of Winemaking for Beginners" -msgstr[0] "" +msgstr[0] "酿酒入门" #. ~ Description for {'str': 'Winemaking for Beginners', 'str_pl': 'copies of #. Winemaking for Beginners'} @@ -62626,7 +62825,7 @@ msgstr "酿酒,是一种艺术。这本书教你如何在字里行间画蜡笔 #: data/json/items/book/cooking.json msgid "You Can Can at Home" msgid_plural "copies of You Can Can at Home" -msgstr[0] "" +msgstr[0] "在家也能罐罐头" #. ~ Description for {'str': 'You Can Can at Home', 'str_pl': 'copies of You #. Can Can at Home'} @@ -62640,7 +62839,7 @@ msgstr "这本入门级家庭罐装指南讨论了不同酸度和原料含量在 #: data/json/items/book/cooking.json msgid "Can Sealer Instructions" msgid_plural "copies of Can Sealer Instructions" -msgstr[0] "" +msgstr[0] "封罐机说明书" #. ~ Description for {'str': 'Can Sealer Instructions', 'str_pl': 'copies of #. Can Sealer Instructions'} @@ -62654,7 +62853,7 @@ msgstr "这份内容枯燥的家用锡罐密封机的说明书清楚描述了此 #: data/json/items/book/cooking.json msgid "The Baker's Companion" msgid_plural "copies of The Baker's Companion" -msgstr[0] "" +msgstr[0] "面包师伴侣手册" #. ~ Description for {'str': "The Baker's Companion", 'str_pl': "copies of The #. Baker's Companion"} @@ -62666,7 +62865,7 @@ msgstr "这本书宣称能够教会你制作各式烘培配方,从蛋糕到舒 #: data/json/items/book/cooking.json msgid "Fermenting Culture" msgid_plural "copies of Fermenting Culture" -msgstr[0] "" +msgstr[0] "发酵的文化" #. ~ Description for {'str': 'Fermenting Culture', 'str_pl': 'copies of #. Fermenting Culture'} @@ -62680,7 +62879,7 @@ msgstr "发酵作为一种烹饪方法,直到最近才在大灾变之前重新 #: data/json/items/book/cooking.json msgid "Out of the Holler and into the Home: A guide to home distilation. " msgid_plural "copies of Out of the Holler" -msgstr[0] "" +msgstr[0] "走出喧嚣" #. ~ Description for {'str': 'Out of the Holler and into the Home: A guide to #. home distilation. ', 'str_pl': 'copies of Out of the Holler'} @@ -62693,7 +62892,7 @@ msgstr "一本描述家庭蒸馏酒历史的书。每一章都包含一个与章 #: data/json/items/book/cooking.json msgid "Sweets for your Sweet Child" msgid_plural "copies of Sweets for Sweet" -msgstr[0] "" +msgstr[0] "给甜心的甜品" #. ~ Description for {'str': 'Sweets for your Sweet Child', 'str_pl': 'copies #. of Sweets for Sweet'} @@ -62707,7 +62906,7 @@ msgstr "《给甜心的甜品》是一本在有小孩的父母中最畅销的烹 #: data/json/items/book/cooking.json msgid "Pocket Survival Cookbook" msgid_plural "copies of Pocket Survival Cookbook" -msgstr[0] "" +msgstr[0] "生存菜谱口袋本" #. ~ Description for {'str': 'Pocket Survival Cookbook', 'str_pl': 'copies of #. Pocket Survival Cookbook'} @@ -62720,7 +62919,7 @@ msgstr "市面上体积最小的菜谱,只卖给驴友。内含与它小体积 #: data/json/items/book/cooking.json msgid "Tasting India" msgid_plural "copies of Tasting India" -msgstr[0] "" +msgstr[0] "寻味印度" #. ~ Description for {'str': 'Tasting India', 'str_pl': 'copies of Tasting #. India'} @@ -62733,7 +62932,7 @@ msgstr "一本厚厚的精装书,它既是一本烹饪书,又是一本介绍 #: data/json/items/book/cutting.json msgid "All About Swords" msgid_plural "issues of All About Swords" -msgstr[0] "" +msgstr[0] "剑术大全" #. ~ Description for {'str': 'All About Swords', 'str_pl': 'issues of All #. About Swords'} @@ -62759,7 +62958,7 @@ msgstr "看起來似乎是對刀刃武器的戰鬥指導, 但是畫質不佳的 #: data/json/items/book/cutting.json msgid "Spetsnaz Knife Techniques" msgid_plural "copies of Spetsnaz Knife Techniques" -msgstr[0] "" +msgstr[0] "雪域特战队的刀具技术" #. ~ Description for {'str': 'Spetsnaz Knife Techniques', 'str_pl': 'copies of #. Spetsnaz Knife Techniques'} @@ -62770,7 +62969,7 @@ msgstr "一本俄文寫的書, 有關刀戰鬥的技巧。" #: data/json/items/book/dodge.json msgid "Dance Dance Dance!" msgid_plural "issues of Dance Dance Dance!" -msgstr[0] "" +msgstr[0] "舞 舞 舞!" #. ~ Description for {'str': 'Dance Dance Dance!', 'str_pl': 'issues of Dance #. Dance Dance!'} @@ -62781,7 +62980,7 @@ msgstr "現在就來學跳舞吧。" #: data/json/items/book/dodge.json msgid "The Book of Dances" msgid_plural "copies of The Book of Dances" -msgstr[0] "" +msgstr[0] "舞蹈教程" #. ~ Description for {'str': 'The Book of Dances', 'str_pl': 'copies of The #. Book of Dances'} @@ -62795,7 +62994,7 @@ msgstr "這本厚重的書籍記錄了全世界的舞蹈細節。感知高的讀 #: data/json/items/book/dodge.json msgid "Break a Leg!" msgid_plural "copies of Break a Leg!" -msgstr[0] "" +msgstr[0] "祝你表演成功!" #. ~ Description for {'str': 'Break a Leg!', 'str_pl': 'copies of Break a #. Leg!'} @@ -62806,7 +63005,7 @@ msgstr "給兒童閱讀的表演與舞台藝術指南。" #: data/json/items/book/driving.json msgid "AAA Guide" msgid_plural "copies of AAA Guide" -msgstr[0] "" +msgstr[0] "AAA年度手册" #. ~ Description for {'str': 'AAA Guide', 'str_pl': 'copies of AAA Guide'} #: data/json/items/book/driving.json @@ -62829,7 +63028,7 @@ msgstr "這雜誌裡面有許多關於車輛以及駕駛的文章。" #: data/json/items/book/driving.json msgid "The Rules of the Road" msgid_plural "copies of The Rules of the Road" -msgstr[0] "" +msgstr[0] "交通法规" #. ~ Description for {'str': 'The Rules of the Road', 'str_pl': 'copies of The #. Rules of the Road'} @@ -62851,7 +63050,7 @@ msgstr "一本觀光導向的城市景點指南。這個特殊的版本顯然是 #: data/json/items/book/electronics.json msgid "Advanced Electronics" msgid_plural "copies of Advanced Electronics" -msgstr[0] "" +msgstr[0] "高级电子技术" #. ~ Description for {'str': 'Advanced Electronics', 'str_pl': 'copies of #. Advanced Electronics'} @@ -62875,7 +63074,7 @@ msgstr "一個有趣的業餘無線電雜誌, 內含大量的圖表和插圖, #: data/json/items/book/electronics.json msgid "What's a Transistor?" msgid_plural "copies of What's a Transistor?" -msgstr[0] "" +msgstr[0] "什么是晶体管?" #. ~ Description for {'str': "What's a Transistor?", 'str_pl': "copies of #. What's a Transistor?"} @@ -62886,7 +63085,7 @@ msgstr "一本基礎的電子與電路設計的手冊。" #: data/json/items/book/electronics.json msgid "Amateur Home Radio for Enthusiasts" msgid_plural "copies of Amateur Home Radio for Enthusiasts" -msgstr[0] "" +msgstr[0] "无线电爱好者" #. ~ Description for {'str': 'Amateur Home Radio for Enthusiasts', 'str_pl': #. 'copies of Amateur Home Radio for Enthusiasts'} @@ -62911,7 +63110,7 @@ msgstr "這表的一面印滿了無意義的混亂字元, 但另一面卻有複 #: data/json/items/book/electronics.json msgid "Augmentative Tech Review" msgid_plural "issues of Augmentative Tech Review" -msgstr[0] "" +msgstr[0] "人体强化科技年鉴" #. ~ Description for {'str': 'Augmentative Tech Review', 'str_pl': 'issues of #. Augmentative Tech Review'} @@ -62968,7 +63167,7 @@ msgstr "一套關於製作模組的指示。安裝在無線電站終端機後, #: data/json/items/book/electronics.json msgid "Electronic Circuit Theory" msgid_plural "copies of Electronic Circuit Theory" -msgstr[0] "" +msgstr[0] "电子电路理论" #. ~ Description for {'str': 'Electronic Circuit Theory', 'str_pl': 'copies of #. Electronic Circuit Theory'} @@ -62980,7 +63179,7 @@ msgstr "一本講述電路理論的進階大學課本, 包含了設計與組織 #: data/json/items/book/electronics.json msgid "Robots for Fun & Profit" msgid_plural "copies of Robots for Fun & Profit" -msgstr[0] "" +msgstr[0] "机器人简单造" #. ~ Description for {'str': 'Robots for Fun & Profit', 'str_pl': 'copies of #. Robots for Fun & Profit'} @@ -62993,7 +63192,7 @@ msgstr "少見的機器人製造刊物, 內容包含許多製造指引與製造 #: data/json/items/book/electronics.json msgid "schematics" msgid_plural "schematics" -msgstr[0] "" +msgstr[0] "原理图" #: data/json/items/book/electronics.json msgid "nurse bot schematics" @@ -63184,7 +63383,7 @@ msgstr "軍規探照燈的裝配藍圖、設計規格和技術圖紙。其中大 #: data/json/items/book/electronics.json msgid "hauler bot schematics" msgid_plural "hauler bot schematics" -msgstr[0] "" +msgstr[0] "运输机器人原理图" #. ~ Description for {'str_sp': 'hauler bot schematics'} #: data/json/items/book/electronics.json @@ -63197,7 +63396,7 @@ msgstr "运输机器人的组合施工图、设计规范以及技术图纸。其 #: data/json/items/book/fabrication.json msgid "The Art of Glassblowing" msgid_plural "copies of The Art of Glassblowing" -msgstr[0] "" +msgstr[0] "玻璃吹制工艺" #. ~ Description for {'str': 'The Art of Glassblowing', 'str_pl': 'copies of #. The Art of Glassblowing'} @@ -63210,7 +63409,7 @@ msgstr "一本講解傳統玻璃吹制技術的教科書。" #: data/json/items/book/fabrication.json msgid "Antique Adornments" msgid_plural "copies of Antique Adornments" -msgstr[0] "" +msgstr[0] "古代饰品大全" #. ~ Description for {'str': 'Antique Adornments', 'str_pl': 'copies of #. Antique Adornments'} @@ -63223,7 +63422,7 @@ msgstr "一本附有插圖, 廣泛地介紹王冠、手鐲、項鍊以及其他 #: data/json/items/book/fabrication.json msgid "Crafty Crafter's Quarterly" msgid_plural "Crafty Crafter's Quarterlies" -msgstr[0] "" +msgstr[0] "专业手工季刊" #. ~ Description for {'str': "Crafty Crafter's Quarterly", 'str_pl': "Crafty #. Crafter's Quarterlies"} @@ -63236,7 +63435,7 @@ msgstr "每季出刊, 主要介紹可以用強力膠製造的手工藝品雜誌 #: data/json/items/book/fabrication.json msgid "101 Crafts for Beginners" msgid_plural "copies of 101 Crafts for Beginners" -msgstr[0] "" +msgstr[0] "手工艺初学者入门" #. ~ Description for {'str': '101 Crafts for Beginners', 'str_pl': 'copies of #. 101 Crafts for Beginners'} @@ -63249,7 +63448,7 @@ msgstr "一本巨細靡遺, 介紹數百種製造方法的新手工具書。" #: data/json/items/book/fabrication.json msgid "The Fletcher's Friend" msgid_plural "copies of The Fletcher's Friend" -msgstr[0] "" +msgstr[0] "箭客之友" #. ~ Description for {'str': "The Fletcher's Friend", 'str_pl': "copies of The #. Fletcher's Friend"} @@ -63266,7 +63465,7 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Bowyer's Buddy" msgid_plural "copies of The Bowyer's Buddy" -msgstr[0] "" +msgstr[0] "弓师之邻" #. ~ Description for {'str': "The Bowyer's Buddy", 'str_pl': "copies of The #. Bowyer's Buddy"} @@ -63280,7 +63479,7 @@ msgstr "這本厚重的書是寫給需要自行手工製作弓的人。書裡面 #: data/json/items/book/fabrication.json msgid "The Handloader's Helper" msgid_plural "copies of The Handloader's Helper" -msgstr[0] "" +msgstr[0] "复装弹药大全" #. ~ Description for {'str': "The Handloader's Helper", 'str_pl': "copies of #. The Handloader's Helper"} @@ -63326,7 +63525,7 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Streetfighter's Sidekick" msgid_plural "copies of The Streetfighter's Sidekick" -msgstr[0] "" +msgstr[0] "街霸特刊" #. ~ Description for {'str': "The Streetfighter's Sidekick", 'str_pl': "copies #. of The Streetfighter's Sidekick"} @@ -63342,7 +63541,7 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Art of Japanese Armormaking" msgid_plural "copies of The Art of Japanese Armormaking" -msgstr[0] "" +msgstr[0] "日式造甲艺术图册" #. ~ Description for {'str': 'The Art of Japanese Armormaking', 'str_pl': #. 'copies of The Art of Japanese Armormaking'} @@ -63355,7 +63554,7 @@ msgstr "以深度文章與技術角度, 介紹古老的日本武士盔甲製作 #: data/json/items/book/fabrication.json msgid "Arms and Armor of Imperial China" msgid_plural "copies of Arms and Armor of Imperial China" -msgstr[0] "" +msgstr[0] "古代中国的武器和护甲" #. ~ Description for {'str': 'Arms and Armor of Imperial China', 'str_pl': #. 'copies of Arms and Armor of Imperial China'} @@ -63370,7 +63569,7 @@ msgstr "這本教科書詳細介紹中國古代軍事史, 尤其側重於歷史 #: data/json/items/book/fabrication.json msgid "Studies in Historic Armorsmithing" msgid_plural "copies of Studies in Historic Armorsmithing" -msgstr[0] "" +msgstr[0] "盔甲制造史研究" #. ~ Description for {'str': 'Studies in Historic Armorsmithing', 'str_pl': #. 'copies of Studies in Historic Armorsmithing'} @@ -63383,7 +63582,7 @@ msgstr "以深度文章與技術角度, 介紹古老的歐洲裝甲製作技術, #: data/json/items/book/fabrication.json msgid "DIY Compendium" msgid_plural "copies of DIY Compendium" -msgstr[0] "" +msgstr[0] "DIY手册" #. ~ Description for {'str': 'DIY Compendium', 'str_pl': 'copies of DIY #. Compendium'} @@ -63396,7 +63595,7 @@ msgstr "一本厚重, 介紹各種可以增進生活樂趣的DIY工具書。" #: data/json/items/book/fabrication.json msgid "A History of Firefighting" msgid_plural "copies of A History of Firefighting" -msgstr[0] "" +msgstr[0] "消防技术史" #. ~ Description for {'str': 'A History of Firefighting', 'str_pl': 'copies of #. A History of Firefighting'} @@ -63410,7 +63609,7 @@ msgstr "這本專業讀物深入淺出地講述了從古至今的消防歷史, #: data/json/items/book/fabrication.json msgid "Art and Science of Chemical Warfare" msgid_plural "copies of Art and Science of Chemical Warfare" -msgstr[0] "" +msgstr[0] "化学战中的艺术与科学" #. ~ Description for {'str': 'Art and Science of Chemical Warfare', 'str_pl': #. 'copies of Art and Science of Chemical Warfare'} @@ -63425,7 +63624,7 @@ msgstr "這本專業讀物深入淺出地講述了從古至今的化學武器歷 #: data/json/items/book/fabrication.json msgid "The Swords of the Samurai" msgid_plural "copies of The Swords of the Samurai" -msgstr[0] "" +msgstr[0] "武士锻造图册" #. ~ Description for {'str': 'The Swords of the Samurai', 'str_pl': 'copies of #. The Swords of the Samurai'} @@ -63439,7 +63638,7 @@ msgstr "以深度文章與技術角度, 介紹古老的日本武器鑄造技術, #: data/json/items/book/fabrication.json msgid "The Historic Weaponsmith" msgid_plural "copies of The Historic Weaponsmith" -msgstr[0] "" +msgstr[0] "武器制造史" #. ~ Description for {'str': 'The Historic Weaponsmith', 'str_pl': 'copies of #. The Historic Weaponsmith'} @@ -63453,7 +63652,7 @@ msgstr "以深度文章與技術角度, 介紹古老的歐洲武器鑄造技術, #: data/json/items/book/fabrication.json msgid "Welding and Metallurgy" msgid_plural "copies of Welding and Metallurgy" -msgstr[0] "" +msgstr[0] "焊接与冶金学百科" #. ~ Description for {'str': 'Welding and Metallurgy', 'str_pl': 'copies of #. Welding and Metallurgy'} @@ -63466,7 +63665,7 @@ msgstr "一本頗為技術性的教科書, 教導成為一個更好的焊工所 #: data/json/items/book/fabrication.json msgid "101 Home Repairs" msgid_plural "copies of 101 Home Repairs" -msgstr[0] "" +msgstr[0] "家具修理入门" #. ~ Description for {'str': '101 Home Repairs', 'str_pl': 'copies of 101 Home #. Repairs'} @@ -63479,7 +63678,7 @@ msgstr "一本平装书,为新手木匠详细提供了进行家居修缮的入 #: data/json/items/book/fabrication.json msgid "The Complete Home Repair Guide" msgid_plural "copies of The Complete Home Repair Guide" -msgstr[0] "" +msgstr[0] "家庭维修完全指南" #. ~ Description for {'str': 'The Complete Home Repair Guide', 'str_pl': #. 'copies of The Complete Home Repair Guide'} @@ -63503,7 +63702,7 @@ msgstr "每月出刊的雜誌, 介紹鳥籠與建構方式。" #: data/json/items/book/fabrication.json msgid "Building for Beginners" msgid_plural "copies of Building for Beginners" -msgstr[0] "" +msgstr[0] "建筑学入门" #. ~ Description for {'str': 'Building for Beginners', 'str_pl': 'copies of #. Building for Beginners'} @@ -63516,7 +63715,7 @@ msgstr "一個大型的平裝書, 詳細介紹幾個初學者的建築工程。" #: data/json/items/book/fabrication.json msgid "Engineering 301" msgid_plural "copies of Engineering 301" -msgstr[0] "" +msgstr[0] "建筑学进阶" #. ~ Description for {'str': 'Engineering 301', 'str_pl': 'copies of #. Engineering 301'} @@ -63544,7 +63743,7 @@ msgstr "" #: data/json/items/book/fabrication.json msgid "The Essential Oil Enthusiasts Handbook" msgid_plural "copies of The Essential Oil Enthusiasts Handbook" -msgstr[0] "" +msgstr[0] "精油爱好者指南" #. ~ Description for {'str': 'The Essential Oil Enthusiasts Handbook', #. 'str_pl': 'copies of The Essential Oil Enthusiasts Handbook'} @@ -63558,7 +63757,7 @@ msgstr "一本沉重的精装书,详细描述了精油的制作过程,并附 #: data/json/items/book/fabrication.json msgid "Concrete Constructions" msgid_plural "copies of Concrete Constructions" -msgstr[0] "" +msgstr[0] "混凝土建筑学" #. ~ Description for {'str': 'Concrete Constructions', 'str_pl': 'copies of #. Concrete Constructions'} @@ -63571,7 +63770,7 @@ msgstr "这本书介绍了混凝土的各类主要用途。同时详细说明了 #: data/json/items/book/firstaid.json msgid "Guide to Advanced Emergency Care" msgid_plural "copies of Guide to Advanced Emergency Care" -msgstr[0] "" +msgstr[0] "高级急救护理指南" #. ~ Description for {'str': 'Guide to Advanced Emergency Care', 'str_pl': #. 'copies of Guide to Advanced Emergency Care'} @@ -63584,7 +63783,7 @@ msgstr "一本厚厚的教科書, 教導醫護人員進階的急救和現場處 #: data/json/items/book/firstaid.json msgid "Paramedics" msgid_plural "issues of Paramedics" -msgstr[0] "" +msgstr[0] "急救医师杂志" #. ~ Description for {'str': 'Paramedics', 'str_pl': 'issues of Paramedics'} #: data/json/items/book/firstaid.json @@ -63594,7 +63793,7 @@ msgstr "一本提供給緊急醫療人員的教育性雜誌。" #: data/json/items/book/firstaid.json msgid "The Big Book of First Aid" msgid_plural "copies of The Big Book of First Aid" -msgstr[0] "" +msgstr[0] "急救指南书" #. ~ Description for {'str': 'The Big Book of First Aid', 'str_pl': 'copies of #. The Big Book of First Aid'} @@ -63605,7 +63804,7 @@ msgstr "這本書又大又重, 充滿了有關於急救的大量資訊。" #: data/json/items/book/firstaid.json msgid "Pocket Guide to First Aid" msgid_plural "copies of Pocket Guide to First Aid" -msgstr[0] "" +msgstr[0] "急救口袋书" #. ~ Description for {'str': 'Pocket Guide to First Aid', 'str_pl': 'copies of #. Pocket Guide to First Aid'} @@ -63619,7 +63818,7 @@ msgstr "這是一本口袋大小的皮革封面的急救指南, 有著簡單的 #: data/json/items/book/firstaid.json msgid "First Responder Handbook" msgid_plural "copies of First Responder Handbook" -msgstr[0] "" +msgstr[0] "现场急救员手册" #. ~ Description for {'str': 'First Responder Handbook', 'str_pl': 'copies of #. First Responder Handbook'} @@ -63632,7 +63831,7 @@ msgstr "一本精裝書, 詳細介紹了進階的急救技術與適合現場操 #: data/json/items/book/firstaid.json msgid "First Aid Kit Instruction Booklet" msgid_plural "copies of First Aid Kit Instruction Booklet" -msgstr[0] "" +msgstr[0] "急救包使用手册" #. ~ Description for {'str': 'First Aid Kit Instruction Booklet', 'str_pl': #. 'copies of First Aid Kit Instruction Booklet'} @@ -63643,7 +63842,7 @@ msgstr "提供圖解指南, 教你如何進行急救。" #: data/json/items/book/firstaid.json msgid "Physicians' Desk Reference" msgid_plural "copies of Physicians' Desk Reference" -msgstr[0] "" +msgstr[0] "内科医生案头参考资料" #. ~ Description for {'str': "Physicians' Desk Reference", 'str_pl': "copies #. of Physicians' Desk Reference"} @@ -63662,7 +63861,7 @@ msgstr "" #: data/json/items/book/firstaid.json msgid "Merck Veterinary Manual" msgid_plural "copies of Merck Veterinary Manual" -msgstr[0] "" +msgstr[0] "默克兽医手册" #. ~ Description for {'str': 'Merck Veterinary Manual', 'str_pl': 'copies of #. Merck Veterinary Manual'} @@ -63680,7 +63879,7 @@ msgstr "" #: data/json/items/book/gun.json msgid "Guns n Ammo" msgid_plural "issues of Guns n Ammo" -msgstr[0] "" +msgstr[0] "枪与弹杂志" #. ~ Description for {'str': 'Guns n Ammo', 'str_pl': 'issues of Guns n Ammo'} #: data/json/items/book/gun.json @@ -63690,7 +63889,7 @@ msgstr "介紹各類槍械的書籍, 並提供許多使用上的建議。" #: data/json/items/book/gun.json msgid "The Gun Owner's Handbook" msgid_plural "copies of The Gun Owner's Handbook" -msgstr[0] "" +msgstr[0] "持枪者指南" #. ~ Description for {'str': "The Gun Owner's Handbook", 'str_pl': "copies of #. The Gun Owner's Handbook"} @@ -63703,7 +63902,7 @@ msgstr "一本軟皮書, 內容有著關於槍械安全操作、保養、修理 #: data/json/items/book/gun.json msgid "Pocket Guide to Firearm Safety" msgid_plural "copies of Pocket Guide to Firearm Safety" -msgstr[0] "" +msgstr[0] "安全使用枪械口袋书" #. ~ Description for {'str': 'Pocket Guide to Firearm Safety', 'str_pl': #. 'copies of Pocket Guide to Firearm Safety'} @@ -63745,7 +63944,7 @@ msgstr "一個令人難以置信的詳細指南, 內容有關於現代火箭、 #: data/json/items/book/lockpick.json msgid "MIT Guide to Lock Picking" msgid_plural "copies of MIT Guide to Lock Picking" -msgstr[0] "" +msgstr[0] "麻省理工学院开锁指南" #. ~ Description for {'str': 'MIT Guide to Lock Picking', 'str_pl': 'copies of #. MIT Guide to Lock Picking'} @@ -63763,7 +63962,7 @@ msgstr[0] "抽象地圖" #: data/json/items/book/maps.json msgid "scientific operations map" msgid_plural "scientific operations maps" -msgstr[0] "" +msgstr[0] "科学行动地图" #. ~ Use action message for {'str': 'scientific operations map'}. #: data/json/items/book/maps.json @@ -63837,7 +64036,7 @@ msgstr "這是本地區域的路線圖。列出了大眾運輸的路線, 如醫 #: data/json/items/book/maps.json msgid "subway maintenance map" msgid_plural "subway maintenance maps" -msgstr[0] "" +msgstr[0] "地铁维护地图" #. ~ Use action message for subway maintenance map. #: data/json/items/book/maps.json @@ -63922,7 +64121,7 @@ msgstr "一本完整的合氣道指南。" #: data/json/items/book/martial.json msgid "Las Nueve Reglas de la Montante" msgid_plural "copies of Las Nueve Reglas de la Montante" -msgstr[0] "" +msgstr[0] "copies of Las Nueve Reglas de la Montante" #. ~ Description for {'str': 'Las Nueve Reglas de la Montante', 'str_pl': #. 'copies of Las Nueve Reglas de la Montante', '//~': "Don't translate name, @@ -64231,7 +64430,7 @@ msgstr "一本完全翻译的中世纪长杆武器作战指南,其中一章详 #: data/json/items/book/martial.json msgid "Historic European Swordfighting" msgid_plural "Historic European Swordfighting" -msgstr[0] "" +msgstr[0] "中世纪剑术" #. ~ Description for {'str_sp': 'Historic European Swordfighting'} #: data/json/items/book/martial.json @@ -64244,7 +64443,7 @@ msgstr "中世纪剑术的完整指南。比较了德国和意大利传统的长 #: data/json/items/book/mechanics.json msgid "Internal Combustion Fundamentals" msgid_plural "copies of Internal Combustion Fundamentals" -msgstr[0] "" +msgstr[0] "内燃机基础原理" #. ~ Description for {'str': 'Internal Combustion Fundamentals', 'str_pl': #. 'copies of Internal Combustion Fundamentals'} @@ -64257,7 +64456,7 @@ msgstr "一本大學教科書, 詳細介紹了內燃機引擎的操作、維護 #: data/json/items/book/mechanics.json msgid "army improvised field repairs manual" msgid_plural "army improvised field repairs manuals" -msgstr[0] "" +msgstr[0] "军用应急维修手册" #. ~ Description for {'str': 'army improvised field repairs manual'} #: data/json/items/book/mechanics.json @@ -64269,7 +64468,7 @@ msgstr "一本印刷褪色的小手冊, 詳細介紹了一些對車輛進行臨 #: data/json/items/book/mechanics.json msgid "Popular Mechanics" msgid_plural "issues of Popular Mechanics" -msgstr[0] "" +msgstr[0] "大众机械杂志" #. ~ Description for {'str': 'Popular Mechanics', 'str_pl': 'issues of Popular #. Mechanics'} @@ -64282,7 +64481,7 @@ msgstr "一本關於機械創新的雜誌。充滿各種關於科技小玩意的 #: data/json/items/book/mechanics.json msgid "Under the Hood" msgid_plural "copies of Under the Hood" -msgstr[0] "" +msgstr[0] "引擎探秘指南" #. ~ Description for {'str': 'Under the Hood', 'str_pl': 'copies of Under the #. Hood'} @@ -64308,7 +64507,7 @@ msgstr "这本团队日志记满了一个核能研究团队对核能技术的发 #: data/json/items/book/mechanics.json msgid "Biodiesel: Renewable Fuel Resource" msgid_plural "copies of Biodiesel: Renewable Fuel Resource" -msgstr[0] "" +msgstr[0] "生物柴油:可再生燃料资源" #. ~ Description for {'str': 'Biodiesel: Renewable Fuel Resource', 'str_pl': #. 'copies of Biodiesel: Renewable Fuel Resource'} @@ -64319,7 +64518,7 @@ msgstr "一本關於生物柴油的大學教科書。" #: data/json/items/book/mechanics.json msgid "Mechanical Mastery" msgid_plural "copies of Mechanical Mastery" -msgstr[0] "" +msgstr[0] "机械师" #. ~ Description for {'str': 'Mechanical Mastery', 'str_pl': 'copies of #. Mechanical Mastery'} @@ -64344,7 +64543,7 @@ msgstr "一本讓你深入了解各種不同風格近身格鬥的月刊。開頭 #: data/json/items/book/melee.json msgid "Close Quarter Fighting Manual" msgid_plural "copies of Close Quarter Fighting Manual" -msgstr[0] "" +msgstr[0] "CQC指南" #. ~ Description for {'str': 'Close Quarter Fighting Manual', 'str_pl': #. 'copies of Close Quarter Fighting Manual'} @@ -64357,7 +64556,7 @@ msgstr "很好翻的一本精裝書, 內容有插畫來說明簡單的近身格 #: data/json/items/book/misc.json msgid "paperback abstract" msgid_plural "paperback abstracts" -msgstr[0] "" +msgstr[0] "虚拟平装书" #. ~ Description for {'str': 'paperback abstract'} #: data/json/items/book/misc.json @@ -64377,7 +64576,7 @@ msgstr "一本超級英雄漫畫。" #: data/json/items/book/misc.json msgid "King James Bible" msgid_plural "copies of King James Bible" -msgstr[0] "" +msgstr[0] "钦定版圣经" #. ~ Description for {'str': 'King James Bible', 'str_pl': 'copies of King #. James Bible'} @@ -64596,7 +64795,7 @@ msgstr "标题为《逃走的松饼》的民间童话故事集,适合讲给小 #: data/json/items/book/misc.json msgid "Computer Gaming" msgid_plural "issues of Computer Gaming" -msgstr[0] "" +msgstr[0] "电脑游戏杂志" #. ~ Description for {'str': 'Computer Gaming', 'str_pl': 'issues of Computer #. Gaming'} @@ -64618,7 +64817,7 @@ msgstr "報導一堆有名的人, 不論現在他們現在是死是活, 死了 #: data/json/items/book/misc.json msgid "Playboy" msgid_plural "issues of Playboy" -msgstr[0] "" +msgstr[0] "花花公子" #. ~ Description for {'str': 'Playboy', 'str_pl': 'issues of Playboy'} #: data/json/items/book/misc.json @@ -64654,7 +64853,7 @@ msgstr "" #: data/json/items/book/misc.json msgid "Rural Digest-Examiner" msgid_plural "issues of Rural Digest-Examiner" -msgstr[0] "" +msgstr[0] "乡村文摘-调查" #. ~ Description for {'str': 'Rural Digest-Examiner', 'str_pl': 'issues of #. Rural Digest-Examiner'} @@ -65908,7 +66107,7 @@ msgstr "弗雷德里克·马里亚特所著的《彼得·辛普》。" #: data/json/items/book/misc.json msgid "collector's edition book" msgid_plural "collector's edition books" -msgstr[0] "" +msgstr[0] "收藏家版书" #. ~ Description for {'str': "collector's edition book"} #: data/json/items/book/misc.json @@ -66047,7 +66246,7 @@ msgstr "這是泰瑞·普萊契的“The Colour of Magic”的初版。在內封 #: data/json/items/book/misc.json msgid "High Level Commercial and Military Cryptology" msgid_plural "High Level Commercial and Military Cryptology" -msgstr[0] "" +msgstr[0] "高级商业和军事密码" #. ~ Description for {'str_sp': 'High Level Commercial and Military #. Cryptology'} @@ -66062,7 +66261,7 @@ msgstr "" #: data/json/items/book/pistol.json msgid "Tactical Handgun Digest" msgid_plural "issues of Tactical Handgun Digest" -msgstr[0] "" +msgstr[0] "战术手枪文摘" #. ~ Description for {'str': 'Tactical Handgun Digest', 'str_pl': 'issues of #. Tactical Handgun Digest'} @@ -66088,7 +66287,7 @@ msgstr "這本書涵蓋了手槍正確使用的方法, 內容包括安全操作 #: data/json/items/book/rifle.json msgid "Modern Rifleman" msgid_plural "issues of Modern Rifleman" -msgstr[0] "" +msgstr[0] "现代步兵杂志" #. ~ Description for {'str': 'Modern Rifleman', 'str_pl': 'issues of Modern #. Rifleman'} @@ -66113,7 +66312,7 @@ msgstr "一本厚重的軍事手冊, 內容關於自動步槍的使用以及提 #: data/json/items/book/shotgun.json msgid "Trap and Field" msgid_plural "issues of Trap and Field" -msgstr[0] "" +msgstr[0] "抛靶器和射击场" #. ~ Description for {'str': 'Trap and Field', 'str_pl': 'issues of Trap and #. Field'} @@ -66126,7 +66325,7 @@ msgstr "一本深入探討霰彈槍與射擊的書籍。後面有篇關於射擊 #: data/json/items/book/shotgun.json msgid "Shotguns: The Art and Science" msgid_plural "copies of Shotguns: The Art and Science" -msgstr[0] "" +msgstr[0] "霰弹枪:艺术与科学" #. ~ Description for {'str': 'Shotguns: The Art and Science', 'str_pl': #. 'copies of Shotguns: The Art and Science'} @@ -66139,7 +66338,7 @@ msgstr "這本書聲稱能解決霰彈槍用家會面臨的每個問題, 能夠 #: data/json/items/book/smg.json msgid "Submachine Gun Enthusiast" msgid_plural "issues of Submachine Gun Enthusiast" -msgstr[0] "" +msgstr[0] "冲锋枪发烧友杂志" #. ~ Description for {'str': 'Submachine Gun Enthusiast', 'str_pl': 'issues of #. Submachine Gun Enthusiast'} @@ -66152,7 +66351,7 @@ msgstr "一本深入介紹關於衝鋒槍射擊的雜誌。在前面有一篇關 #: data/json/items/book/smg.json msgid "The Submachine Gun Handbook" msgid_plural "copies of The Submachine Gun Handbook" -msgstr[0] "" +msgstr[0] "冲锋枪操作手册" #. ~ Description for {'str': 'The Submachine Gun Handbook', 'str_pl': 'copies #. of The Submachine Gun Handbook'} @@ -66176,7 +66375,7 @@ msgstr "每週的新聞以及一堆有名的人, 不論現在他們現在是死 #: data/json/items/book/speech.json msgid "Self-Esteem for Dummies" msgid_plural "copies of Self-Esteem for Dummies" -msgstr[0] "" +msgstr[0] "励志傻瓜书" #. ~ Description for {'str': 'Self-Esteem for Dummies', 'str_pl': 'copies of #. Self-Esteem for Dummies'} @@ -66187,7 +66386,7 @@ msgstr "充滿了許多展現自信與口才的有用提示。" #: data/json/items/book/speech.json msgid "Principles of Effective Communication" msgid_plural "copies of Principles of Effective Communication" -msgstr[0] "" +msgstr[0] "有效沟通的原则" #. ~ Description for {'str': 'Principles of Effective Communication', #. 'str_pl': 'copies of Principles of Effective Communication'} @@ -66198,7 +66397,7 @@ msgstr "一本精裝書, 教導如何成為一個有效和有說服力的演講 #: data/json/items/book/speech.json msgid "Dungeon Master's Guide: 6th Edition" msgid_plural "copies of Dungeon Master's Guide: 6th Edition" -msgstr[0] "" +msgstr[0] "地下城主指南(第6版)" #. ~ Description for {'str': "Dungeon Master's Guide: 6th Edition", 'str_pl': #. "copies of Dungeon Master's Guide: 6th Edition"} @@ -66249,7 +66448,7 @@ msgstr "一本冗长而复杂的野外生存指南和末日城市求生杂志, #: data/json/items/book/survival.json msgid "Through the Lens" msgid_plural "copies of Through the Lens" -msgstr[0] "" +msgstr[0] "美丽摄影期刊" #. ~ Description for {'str': 'Through the Lens', 'str_pl': 'copies of Through #. the Lens'} @@ -66277,7 +66476,7 @@ msgstr "這是全方位的男性雜誌。有關於健行與野外生存的一些 #: data/json/items/book/survival.json msgid "Outdoor Adventures" msgid_plural "issues of Outdoor Adventures" -msgstr[0] "" +msgstr[0] "户外探险杂志" #. ~ Description for {'str': 'Outdoor Adventures', 'str_pl': 'issues of #. Outdoor Adventures'} @@ -66301,7 +66500,7 @@ msgstr "一本有關於野外求生器具製作與操作的手冊。" #: data/json/items/book/survival.json msgid "Pocket Survival Guide" msgid_plural "copies of Pocket Survival Guide" -msgstr[0] "" +msgstr[0] "生存指南口袋本" #. ~ Description for {'str': 'Pocket Survival Guide', 'str_pl': 'copies of #. Pocket Survival Guide'} @@ -66315,7 +66514,7 @@ msgstr "這個袖珍皮革裝訂的生存指南結合了豐富的資訊, 並且 #: data/json/items/book/survival.json msgid "Autobiography of a Mountain Man" msgid_plural "copies of Autobiography of a Mountain Man" -msgstr[0] "" +msgstr[0] "山人自传" #. ~ Description for {'str': 'Autobiography of a Mountain Man', 'str_pl': #. 'copies of Autobiography of a Mountain Man'} @@ -66329,7 +66528,7 @@ msgstr "一本充滿了在野外生存與有趣歷史故事的詳盡書籍, 可 #: data/json/items/book/survival.json msgid "Outdoor Survival Guide" msgid_plural "copies of Outdoor Survival Guide" -msgstr[0] "" +msgstr[0] "户外生存指南" #. ~ Description for {'str': 'Outdoor Survival Guide', 'str_pl': 'copies of #. Outdoor Survival Guide'} @@ -66342,7 +66541,7 @@ msgstr "一本平裝的厚書本, 包含了關於在野外生存的重要資訊, #: data/json/items/book/survival.json msgid "Natural Remedies of New England" msgid_plural "copies of Natural Remedies of New England" -msgstr[0] "" +msgstr[0] "新英格兰的天然草药" #. ~ Description for {'str': 'Natural Remedies of New England', 'str_pl': #. 'copies of Natural Remedies of New England'} @@ -66355,7 +66554,7 @@ msgstr "一本皮革装订的手稿,描述了多种本地的天然草药并附 #: data/json/items/book/swimming.json msgid "Swim Planet" msgid_plural "issues of Swim Planet" -msgstr[0] "" +msgstr[0] "泳动星球期刊" #. ~ Description for {'str': 'Swim Planet', 'str_pl': 'issues of Swim Planet'} #: data/json/items/book/swimming.json @@ -66365,7 +66564,7 @@ msgstr "世界領先的水上運動雜誌。" #: data/json/items/book/swimming.json msgid "Water Survival Training Field Manual" msgid_plural "copies of Water Survival Training Field Manual" -msgstr[0] "" +msgstr[0] "水域生存训练手册" #. ~ Description for {'str': 'Water Survival Training Field Manual', 'str_pl': #. 'copies of Water Survival Training Field Manual'} @@ -66417,7 +66616,7 @@ msgstr "內容呈現許多關於針織, 鉤針, 刺繡的多樣化裁縫書籍 #: data/json/items/book/tailor.json msgid "Sew What? Clothing!" msgid_plural "copies of Sew What? Clothing!" -msgstr[0] "" +msgstr[0] "服装缝纫教程" #. ~ Description for {'str': 'Sew What? Clothing!', 'str_pl': 'copies of Sew #. What? Clothing!'} @@ -66441,7 +66640,7 @@ msgstr "這個皮革文件夾曾經為某個服裝設計師所擁有, 裡面是 #: data/json/items/book/tailor.json msgid "Traditional Japanese Kimono" msgid_plural "copies of Traditional Japanese Kimono" -msgstr[0] "" +msgstr[0] "日本传统和服" #. ~ Description for {'str': 'Traditional Japanese Kimono', 'str_pl': 'copies #. of Traditional Japanese Kimono'} @@ -66452,7 +66651,7 @@ msgstr "一本关于日本传统服装制造的插图教科书。" #: data/json/items/book/tailor.json msgid "Friendly, Humane Fashion" msgid_plural "copies of Friendly, Humane Fashion" -msgstr[0] "" +msgstr[0] "新时尚:更友善且人道" #. ~ Description for {'str': 'Friendly, Humane Fashion', 'str_pl': 'copies of #. Friendly, Humane Fashion'} @@ -66468,7 +66667,7 @@ msgstr "" #: data/json/items/book/tailor.json msgid "Sewing Techniques for Designers" msgid_plural "copies of Sewing Techniques for Designers" -msgstr[0] "" +msgstr[0] "时装设计师技术指导书" #. ~ Description for {'str': 'Sewing Techniques for Designers', 'str_pl': #. 'copies of Sewing Techniques for Designers'} @@ -66481,7 +66680,7 @@ msgstr "一本精裝的裁縫大百科, 充滿了有關專業服裝設計的豐 #: data/json/items/book/throw.json msgid "Diskobolus" msgid_plural "issues of Diskobolus" -msgstr[0] "" +msgstr[0] "掷铁饼者杂志" #. ~ Description for {'str': 'Diskobolus', 'str_pl': 'issues of Diskobolus'} #: data/json/items/book/throw.json @@ -66491,7 +66690,7 @@ msgstr "一本半年出刊的雜誌, 介紹專業的鐵餅投擲的藝術和科 #: data/json/items/book/throw.json msgid "The Complete Guide to Pitching" msgid_plural "copies of The Complete Guide to Pitching" -msgstr[0] "" +msgstr[0] "投球手完全指南" #. ~ Description for {'str': 'The Complete Guide to Pitching', 'str_pl': #. 'copies of The Complete Guide to Pitching'} @@ -66504,7 +66703,7 @@ msgstr "一本關於棒球投手的詳盡指導。教你如何使用各種技巧 #: data/json/items/book/traps.json msgid "How to Trap Anything" msgid_plural "copies of How to Trap Anything" -msgstr[0] "" +msgstr[0] "如何设陷阱" #. ~ Description for {'str': 'How to Trap Anything', 'str_pl': 'copies of How #. to Trap Anything'} @@ -66516,7 +66715,7 @@ msgstr "手冊中介紹了如何設置和解除各式各樣的陷阱。" #: data/json/items/book/traps.json msgid "Trapper's Life" msgid_plural "issues of Trapper's Life" -msgstr[0] "" +msgstr[0] "陷捕者生存法则" #. ~ Description for {'str': "Trapper's Life", 'str_pl': "issues of Trapper's #. Life"} @@ -66529,7 +66728,7 @@ msgstr "一本深度的陷阱比賽雜誌。有很多的文章和圖表, 講解 #: data/json/items/book/traps.json msgid "The Modern Trapper" msgid_plural "copies of The Modern Trapper" -msgstr[0] "" +msgstr[0] "现代捕猎者" #. ~ Description for {'str': 'The Modern Trapper', 'str_pl': 'copies of The #. Modern Trapper'} @@ -66540,7 +66739,7 @@ msgstr "一本充滿詳盡內容的書, 內容說明了各種製作陷阱的方 #: data/json/items/book/traps.json msgid "FM 20-32 Mine/Countermine Operations manual" msgid_plural "copies of FM 20-32 Mine/Countermine Operations manual" -msgstr[0] "" +msgstr[0] "FM 20-32陆军手册:地雷与反地雷" #. ~ Description for {'str': 'FM 20-32 Mine/Countermine Operations manual', #. 'str_pl': 'copies of FM 20-32 Mine/Countermine Operations manual'} @@ -66555,7 +66754,7 @@ msgstr "一本沉重的军事战地手册,讲述了地雷战中的原则、不 #: data/json/items/book/traps.json msgid "The Compleat Trapper" msgid_plural "copies of The Compleat Trapper" -msgstr[0] "" +msgstr[0] "陷阱达人" #. ~ Description for {'//~': 'The spelling is intentionally archaic, as this #. form is commonly used in the titles of books.', 'str': 'The Compleat @@ -66595,7 +66794,7 @@ msgstr "一本血脈僨張的拳擊月刊。裡面刊載了相當大量關於拳 #: data/json/items/book/unarmed.json msgid "101 Wrestling Moves" msgid_plural "copies of 101 Wrestling Moves" -msgstr[0] "" +msgstr[0] "摔跤动作入门" #. ~ Description for {'str': '101 Wrestling Moves', 'str_pl': 'copies of 101 #. Wrestling Moves'} @@ -66609,17 +66808,17 @@ msgstr "一本摔跤手册,印刷质量很差,草草进行装订后就发行 #: data/json/items/classes/book.json msgid "readable magazine" msgid_plural "readable magazines" -msgstr[0] "" +msgstr[0] "可读杂志" #: data/json/items/classes/book.json msgid "martial art manual" msgid_plural "martial art manuals" -msgstr[0] "" +msgstr[0] "武术手册" #: data/json/items/classes/comestible.json msgid "Spice" msgid_plural "Spices" -msgstr[0] "" +msgstr[0] "香料" #: data/json/items/classes/gun.json msgid "base gun" @@ -66697,7 +66896,7 @@ msgstr[0] "左輪手槍" #: data/json/items/classes/gun.json msgid "cap & ball revolver" msgid_plural "cap & ball revolvers" -msgstr[0] "" +msgstr[0] "雷管左轮手枪" #: data/json/items/classes/gun.json msgid "energy pistol" @@ -66737,7 +66936,7 @@ msgstr[0] "单发步枪" #: data/json/items/classes/gun.json msgid "home-made rifle" msgid_plural "home-made rifles" -msgstr[0] "" +msgstr[0] "自制步枪" #: data/json/items/classes/gun.json msgid "energy rifle" @@ -66792,7 +66991,7 @@ msgstr "咔嚓咔嚓。" #: data/json/items/classes/gun.json msgid "base race shotgun, pump" msgid_plural "base race shotguns, pump" -msgstr[0] "" +msgstr[0] "基础泵动式霰弹枪" #: data/json/items/classes/gun.json msgid "base SMG" @@ -66830,7 +67029,7 @@ msgstr[0] "基础化学喷雾器" #: data/json/items/classes/magazine.json msgid "ammo belt" msgid_plural "ammo belts" -msgstr[0] "" +msgstr[0] "子弹带" #. ~ Description for {'str': 'ammo belt'} #: data/json/items/classes/magazine.json @@ -66841,12 +67040,12 @@ msgstr "一條彈鏈。子彈間有著金屬鏈結, 會在發射後解體。" #: data/json/items/classes/range.json msgid "base range weapon" msgid_plural "base range weapons" -msgstr[0] "" +msgstr[0] "基础远程武器" #: data/json/items/classes/range.json msgid "base bow" msgid_plural "base bows" -msgstr[0] "" +msgstr[0] "基础弓" #: data/json/items/classes/range.json msgid "base crossbow" @@ -66861,7 +67060,7 @@ msgstr[0] "基础手弩" #: data/json/items/classes/range.json msgid "base slingshot" msgid_plural "base slingshots" -msgstr[0] "" +msgstr[0] "基础弹弓" #: data/json/items/classes/range.json msgid "base sling" @@ -66877,7 +67076,7 @@ msgstr "投擲" #: data/mods/No_Fungi/comestibles.json msgid "marloss wine" msgid_plural "marloss wine" -msgstr[0] "" +msgstr[0] "马洛斯酒" #. ~ Description for {'str_sp': 'marloss wine'} #: data/json/items/comestibles/alcohol.json @@ -67110,7 +67309,7 @@ msgstr "一種融合許多烈酒的神奇調酒,但喝起來又沒酒味。 #: data/json/items/comestibles/alcohol.json msgid "screwdriver cocktail" msgid_plural "screwdriver cocktails" -msgstr[0] "" +msgstr[0] "螺丝刀鸡尾酒" #. ~ Description for screwdriver cocktail #: data/json/items/comestibles/alcohol.json @@ -67177,7 +67376,7 @@ msgstr "一種清淡可口的酒, 由蒲公英花製成。它有些微氣泡, #: data/json/items/comestibles/alcohol.json msgid "burdock wine" msgid_plural "burdock wine" -msgstr[0] "" +msgstr[0] "牛蒡酒" #. ~ Description for {'str_sp': 'burdock wine'} #: data/json/items/comestibles/alcohol.json @@ -67293,7 +67492,7 @@ msgstr "一種已經在橡木桶中好一段時間的可口啤酒。宛如無月 #: data/json/items/comestibles/alcohol.json msgid "strawberry surprise" msgid_plural "strawberry surprises" -msgstr[0] "" +msgstr[0] "草莓果酒" #. ~ Description for strawberry surprise #: data/json/items/comestibles/alcohol.json @@ -67328,7 +67527,7 @@ msgstr "瓶蓋之內全是最優等的威士忌。" #: data/json/items/comestibles/alcohol.json msgid "single pot still Irish whiskey" msgid_plural "single pot still Irish whiskey" -msgstr[0] "" +msgstr[0] "爱尔兰单壶式蒸馏威士忌" #. ~ Description for {'str_sp': 'single pot still Irish whiskey'} #: data/json/items/comestibles/alcohol.json @@ -67338,7 +67537,7 @@ msgstr "一种由含麦芽和不含麦芽的大麦混合酿成的威士忌。" #: data/json/items/comestibles/alcohol.json msgid "cheap whiskey" msgid_plural "cheap whiskey" -msgstr[0] "" +msgstr[0] "廉价威士忌" #. ~ Description for {'str_sp': 'cheap whiskey'} #: data/json/items/comestibles/alcohol.json @@ -67348,7 +67547,7 @@ msgstr "一种廉价的混合威士忌。" #: data/json/items/comestibles/alcohol.json msgid "Canadian whiskey" msgid_plural "Canadian whiskey" -msgstr[0] "" +msgstr[0] "加拿大威士忌" #. ~ Description for {'str_sp': 'Canadian whiskey'} #: data/json/items/comestibles/alcohol.json @@ -67358,7 +67557,7 @@ msgstr "一种由玉米和黑麦混合酿成的杂粮威士忌酒。" #: data/json/items/comestibles/alcohol.json msgid "sherry" msgid_plural "sherry" -msgstr[0] "" +msgstr[0] "雪利酒" #. ~ Description for {'str_sp': 'sherry'} #: data/json/items/comestibles/alcohol.json @@ -67369,7 +67568,7 @@ msgstr "一瓶源自东印度的索莱拉陈酿。英国绅士的真正佳酿。 #: data/json/items/comestibles/alcohol.json msgid "Bristol Cream" msgid_plural "Bristol Cream" -msgstr[0] "" +msgstr[0] "夏微雪利酒" #. ~ Description for {'str_sp': 'Bristol Cream'} #: data/json/items/comestibles/alcohol.json @@ -67381,7 +67580,7 @@ msgstr "一种高端雪利酒,使用美国橡木桶酿造并熟成,在英国 #: data/json/items/comestibles/alcohol.json msgid "Madeira wine" msgid_plural "Madeira wine" -msgstr[0] "" +msgstr[0] "马德拉酒" #. ~ Description for {'str_sp': 'Madeira wine'} #: data/json/items/comestibles/alcohol.json @@ -67391,7 +67590,7 @@ msgstr "一瓶加入了烈酒强化的马德拉葡萄酒。皇家海军的真正 #: data/json/items/comestibles/alcohol.json msgid "fancy hobo" msgid_plural "fancy hobo" -msgstr[0] "" +msgstr[0] "浪子鸡尾酒" #. ~ Description for {'str_sp': 'fancy hobo'} #: data/json/items/comestibles/alcohol.json @@ -67401,7 +67600,7 @@ msgstr "這味道無疑像一個街友的飲料。" #: data/json/items/comestibles/alcohol.json msgid "kalimotxo" msgid_plural "kalimotxo" -msgstr[0] "" +msgstr[0] "可乐鸡尾酒" #. ~ Description for {'str_sp': 'kalimotxo'} #: data/json/items/comestibles/alcohol.json @@ -67413,7 +67612,7 @@ msgstr "混合等份葡萄酒和可樂。它沒有一些人想像的那麼糟糕 #: data/json/items/comestibles/alcohol.json msgid "bee's knees" msgid_plural "bee's knees" -msgstr[0] "" +msgstr[0] "蜂膝鸡尾酒" #. ~ Description for {'str_sp': "bee's knees"} #: data/json/items/comestibles/alcohol.json @@ -67425,7 +67624,7 @@ msgstr "這種雞尾酒可以追溯到禁酒令時代。琴酒、蜂蜜及檸檬 #: data/json/items/comestibles/alcohol.json msgid "whiskey sour" msgid_plural "whiskey sours" -msgstr[0] "" +msgstr[0] "威士忌酸酒" #. ~ Description for whiskey sour #: data/json/items/comestibles/alcohol.json @@ -67435,7 +67634,7 @@ msgstr "一種威士忌與檸檬汁混合的飲料。" #: data/json/items/comestibles/alcohol.json msgid "honeygold brew" msgid_plural "honeygold brews" -msgstr[0] "" +msgstr[0] "蜜黄酒酿" #. ~ Description for honeygold brew #: data/json/items/comestibles/alcohol.json @@ -67447,7 +67646,7 @@ msgstr "一種混合飲品, 有著其成分的所有優點, 而沒有副作用 #: data/json/items/comestibles/alcohol.json msgid "honey ball" msgid_plural "honey balls" -msgstr[0] "" +msgstr[0] "蚁露" #. ~ Description for honey ball #: data/json/items/comestibles/alcohol.json @@ -67461,7 +67660,7 @@ msgstr "" #: data/json/items/comestibles/alcohol.json msgid "spiked eggnog" msgid_plural "spiked eggnogs" -msgstr[0] "" +msgstr[0] "蛋诺酒" #. ~ Description for spiked eggnog #: data/json/items/comestibles/alcohol.json @@ -67474,7 +67673,7 @@ msgstr "順滑而濃厚, 這杯由牛奶、奶油和蛋混合而成的濃稠飲 #: data/json/items/comestibles/alcohol.json msgid "martini" msgid_plural "martinis" -msgstr[0] "" +msgstr[0] "马提尼酒" #. ~ Description for martini #: data/json/items/comestibles/alcohol.json @@ -67559,7 +67758,7 @@ msgstr "这个罐子装着一团珍贵的面糊,由面粉、水、霉菌和空 #: data/json/items/comestibles/bread.json msgid "sourdough bread" msgid_plural "sourdough breads" -msgstr[0] "" +msgstr[0] "酸面包" #. ~ Description for sourdough bread #: data/json/items/comestibles/bread.json @@ -67571,7 +67770,7 @@ msgstr "健康且飽足,口感更清脆,外殼比酵母麵包更厚。" #: data/json/items/comestibles/bread.json msgid "flatbread" msgid_plural "flatbreads" -msgstr[0] "" +msgstr[0] "面饼" #. ~ Description for flatbread #: data/json/items/comestibles/bread.json @@ -67581,7 +67780,7 @@ msgstr "不加入酵母的簡單麵包。" #: data/json/items/comestibles/bread.json msgid "bread" msgid_plural "breads" -msgstr[0] "" +msgstr[0] "面包" #. ~ Description for bread #: data/json/items/comestibles/bread.json @@ -67601,7 +67800,7 @@ msgstr "用大蒜、油和调味料烹制的面包。" #: data/json/items/comestibles/bread.json msgid "cornbread" msgid_plural "cornbreads" -msgstr[0] "" +msgstr[0] "玉米面包" #. ~ Description for cornbread #: data/json/items/comestibles/bread.json @@ -67611,7 +67810,7 @@ msgstr "健康又可填飽肚子的玉米麵包。" #: data/json/items/comestibles/bread.json msgid "johnnycake" msgid_plural "johnnycakes" -msgstr[0] "" +msgstr[0] "玉米烤饼" #. ~ Description for johnnycake #: data/json/items/comestibles/bread.json @@ -67621,7 +67820,7 @@ msgstr "濃郁美味的炸麵包。" #: data/json/items/comestibles/bread.json msgid "corn tortilla" msgid_plural "corn tortillas" -msgstr[0] "" +msgstr[0] "玉米饼" #. ~ Description for corn tortilla #: data/json/items/comestibles/bread.json @@ -67631,7 +67830,7 @@ msgstr "圓的, 由磨細的玉米粉作成的薄烤餅。" #: data/json/items/comestibles/bread.json msgid "hardtack" msgid_plural "hardtacks" -msgstr[0] "" +msgstr[0] "硬面饼" #. ~ Description for hardtack #: data/json/items/comestibles/bread.json @@ -67643,7 +67842,7 @@ msgstr "乾而無味的麵包產品, 能夠保存很長一段時間。" #: data/json/items/comestibles/bread.json msgid "biscuit" msgid_plural "biscuits" -msgstr[0] "" +msgstr[0] "饼干" #. ~ Description for {'str': 'biscuit'} #: data/json/items/comestibles/bread.json @@ -67653,7 +67852,7 @@ msgstr "美味又飽足, 這個自製餅乾很好吃!" #: data/json/items/comestibles/bread.json msgid "wastebread" msgid_plural "wastebreads" -msgstr[0] "" +msgstr[0] "废土面包" #. ~ Description for wastebread #: data/json/items/comestibles/bread.json @@ -67666,7 +67865,7 @@ msgstr "麵粉是一種好東西來應付這些日子, 多數倖存者使用了 #: data/json/items/comestibles/brewing.json msgid "mycus wine must" msgid_plural "mycus wine musts" -msgstr[0] "" +msgstr[0] "马卡斯酒原汁" #. ~ Description for mycus wine must #: data/json/items/comestibles/brewing.json @@ -67678,7 +67877,7 @@ msgstr "未发酵的马卡斯酒,滑腻的白色混合物,由马卡斯果实 #: data/json/items/comestibles/brewing.json msgid "whiskey wort" msgid_plural "whiskey worts" -msgstr[0] "" +msgstr[0] "威士忌原汁" #. ~ Description for whiskey wort #: data/json/items/comestibles/brewing.json @@ -67700,7 +67899,7 @@ msgstr "完成發酵, 但尚未蒸餾的威士忌。不再帶有甜味。" #: data/json/items/comestibles/brewing.json msgid "fermenting gin mash" msgid_plural "fermenting gin mashes" -msgstr[0] "" +msgstr[0] "杜松子酒发酵原汁" #. ~ Description for {'str': 'fermenting gin mash', 'str_pl': 'fermenting gin #. mashes'} @@ -67711,7 +67910,7 @@ msgstr "未蒸馏的杜松子酒原汁。蒸馏会产生杜松子酒。" #: data/json/items/comestibles/brewing.json msgid "gin mash" msgid_plural "gin mashes" -msgstr[0] "" +msgstr[0] "杜松子酒原汁" #. ~ Description for {'str': 'gin mash', 'str_pl': 'gin mashes'} #: data/json/items/comestibles/brewing.json @@ -67723,7 +67922,7 @@ msgstr "杜松子酒原汁,加入的杜松子经过发酵可为其增添风味 #: data/json/items/comestibles/brewing.json msgid "vodka wort" msgid_plural "vodka worts" -msgstr[0] "" +msgstr[0] "伏特加原汁" #. ~ Description for vodka wort #: data/json/items/comestibles/brewing.json @@ -67745,7 +67944,7 @@ msgstr "完成發酵, 但尚未蒸餾的伏特加。不再帶有甜味。" #: data/json/items/comestibles/brewing.json msgid "rum wort" msgid_plural "rum worts" -msgstr[0] "" +msgstr[0] "朗姆酒原汁" #. ~ Description for rum wort #: data/json/items/comestibles/brewing.json @@ -67767,7 +67966,7 @@ msgstr "完成發酵, 但尚未蒸餾的蘭姆酒。不再帶有甜味。" #: data/json/items/comestibles/brewing.json msgid "fruit wine must" msgid_plural "fruit wine musts" -msgstr[0] "" +msgstr[0] "果酒原汁" #. ~ Description for fruit wine must #: data/json/items/comestibles/brewing.json @@ -67778,7 +67977,7 @@ msgstr "未發酵的水果酒。由甜美的漿果和水果煮沸濃縮而成。 #: data/json/items/comestibles/brewing.json msgid "spiced mead must" msgid_plural "spiced mead musts" -msgstr[0] "" +msgstr[0] "香蜜酒原汁" #. ~ Description for spiced mead must #: data/json/items/comestibles/brewing.json @@ -67788,7 +67987,7 @@ msgstr "未發酵的香料蜜酒。稀釋過的蜂蜜和酵母混合物。" #: data/json/items/comestibles/brewing.json msgid "dandelion wine must" msgid_plural "dandelion wine musts" -msgstr[0] "" +msgstr[0] "蒲公英酒原汁" #. ~ Description for dandelion wine must #: data/json/items/comestibles/brewing.json @@ -67800,7 +67999,7 @@ msgstr "未發酵的蒲公英酒。由水、糖、酵母、蒲公英花瓣混合 #: data/json/items/comestibles/brewing.json msgid "burdock wine must" msgid_plural "burdock wine musts" -msgstr[0] "" +msgstr[0] "牛蒡酒原汁" #. ~ Description for burdock wine must #: data/json/items/comestibles/brewing.json @@ -67812,7 +68011,7 @@ msgstr "还没发酵的牛蒡酒,由水,糖,酵母和牛蒡根混合而成 #: data/json/items/comestibles/brewing.json msgid "pine wine must" msgid_plural "pine wine musts" -msgstr[0] "" +msgstr[0] "松脂酒原汁" #. ~ Description for pine wine must #: data/json/items/comestibles/brewing.json @@ -67824,7 +68023,7 @@ msgstr "未發酵的松脂酒。由水、糖、酵母、松樹樹脂混合而成 #: data/json/items/comestibles/brewing.json msgid "beer wort" msgid_plural "beer worts" -msgstr[0] "" +msgstr[0] "啤酒原汁" #. ~ Description for {'str': 'beer wort'} #: data/json/items/comestibles/brewing.json @@ -67860,7 +68059,7 @@ msgstr "完成發酵, 但尚未蒸餾的私釀烈酒。裡頭有一堆需要過 #: data/json/items/comestibles/brewing.json msgid "unfermented vinegar" msgid_plural "unfermented vinegars" -msgstr[0] "" +msgstr[0] "未发酵醋" #. ~ Description for unfermented vinegar #: data/json/items/comestibles/brewing.json @@ -67872,7 +68071,7 @@ msgstr "混合了水、酒精、果汁, 最終總有一天會變成醋。" #: data/json/items/comestibles/carnivore.json msgid "meat/fish" msgid_plural "meat/fish" -msgstr[0] "" +msgstr[0] "肉/鱼" #: data/json/items/comestibles/carnivore.json msgid "fillet of fish" @@ -67897,7 +68096,7 @@ msgstr "新鮮烹飪過的魚。非常營養。" #: data/json/items/comestibles/carnivore.json msgid "human stomach" msgid_plural "human stomachs" -msgstr[0] "" +msgstr[0] "人胃" #. ~ Description for human stomach #: data/json/items/comestibles/carnivore.json @@ -67907,7 +68106,7 @@ msgstr "人類的胃袋, 比想像中結實。" #: data/json/items/comestibles/carnivore.json msgid "large human stomach" msgid_plural "large human stomachs" -msgstr[0] "" +msgstr[0] "大型人胃" #. ~ Description for large human stomach #: data/json/items/comestibles/carnivore.json @@ -67917,7 +68116,7 @@ msgstr "來自人型生物的大型胃袋, 比想像中結實。" #: data/json/items/comestibles/carnivore.json msgid "chunk of human fat" msgid_plural "chunks of human fat" -msgstr[0] "" +msgstr[0] "人脂肪块" #. ~ Description for {'str': 'chunk of human fat', 'str_pl': 'chunks of human #. fat'} @@ -67928,7 +68127,7 @@ msgstr "一份从人身上切下来的新鲜肥肉块。" #: data/json/items/comestibles/carnivore.json msgid "human tallow" msgid_plural "human tallows" -msgstr[0] "" +msgstr[0] "人油" #. ~ Description for human tallow #: data/json/items/comestibles/carnivore.json @@ -67941,7 +68140,7 @@ msgstr "一块清洗后熬制的白色人类脂肪。可以保存很久并食用 #: data/json/items/comestibles/carnivore.json msgid "human lard" msgid_plural "human lards" -msgstr[0] "" +msgstr[0] "干炼人油" #. ~ Description for human lard #: data/json/items/comestibles/carnivore.json @@ -67964,7 +68163,7 @@ msgstr "從人體屠宰下來的新鮮人肉。" #: data/json/items/comestibles/carnivore.json msgid "cooked creep" msgid_plural "cooked creeps" -msgstr[0] "" +msgstr[0] "熟人肉" #. ~ Description for cooked creep #: data/json/items/comestibles/carnivore.json @@ -68026,7 +68225,7 @@ msgstr "从严重变异的生物身上切下的一小片肉。它闻起来有点 #: data/json/items/comestibles/carnivore.json msgid "mutant humanoid meat" msgid_plural "mutant humanoid meats" -msgstr[0] "" +msgstr[0] "变异人肉" #. ~ Description for mutant humanoid meat #: data/json/items/comestibles/carnivore.json @@ -68039,7 +68238,7 @@ msgstr "从一只严重变异的人形生物身上取得的肉块。它闻起来 #: data/json/items/comestibles/carnivore.json msgid "cooked cretin" msgid_plural "cooked cretins" -msgstr[0] "" +msgstr[0] "煮白痴" #. ~ Description for cooked cretin #: data/json/items/comestibles/carnivore.json @@ -68051,7 +68250,7 @@ msgstr "一块煮熟的变异人肉。现在它不再闻起来像工业废料, #: data/json/items/comestibles/carnivore.json msgid "cooked meat" msgid_plural "cooked meats" -msgstr[0] "" +msgstr[0] "熟肉" #. ~ Description for cooked meat #: data/json/items/comestibles/carnivore.json @@ -68068,7 +68267,7 @@ msgstr[0] "煮熟的肉渣" #: data/json/items/comestibles/carnivore.json msgid "cooked mutant meat" msgid_plural "cooked mutant meats" -msgstr[0] "" +msgstr[0] "变异熟肉" #. ~ Description for cooked mutant meat #: data/json/items/comestibles/carnivore.json @@ -68085,7 +68284,7 @@ msgstr[0] "煮熟的突變體肉碎片" #: data/json/items/comestibles/carnivore.json msgid "raw offal" msgid_plural "raw offals" -msgstr[0] "" +msgstr[0] "生内脏" #. ~ Description for raw offal #: data/json/items/comestibles/carnivore.json @@ -68123,7 +68322,7 @@ msgstr "剛煮過的腸子和器官的肉, 保存在罐頭中。它引不起食 #: data/json/items/comestibles/carnivore.json msgid "raw mutant offal" msgid_plural "raw mutant offals" -msgstr[0] "" +msgstr[0] "生变异内脏" #. ~ Description for raw mutant offal #: data/json/items/comestibles/carnivore.json @@ -68139,7 +68338,7 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "stomach" msgid_plural "stomachs" -msgstr[0] "" +msgstr[0] "胃囊" #. ~ Description for stomach #: data/json/items/comestibles/carnivore.json @@ -68149,7 +68348,7 @@ msgstr "來自林地生物的胃袋, 比想像中結實。" #: data/json/items/comestibles/carnivore.json msgid "large stomach" msgid_plural "large stomachs" -msgstr[0] "" +msgstr[0] "大胃囊" #. ~ Description for large stomach #: data/json/items/comestibles/carnivore.json @@ -68173,7 +68372,7 @@ msgstr[0] "醃人肉" #: data/json/items/comestibles/carnivore.json msgid "monster jerky" msgid_plural "monster jerky" -msgstr[0] "" +msgstr[0] "怪兽肉干" #. ~ Description for {'str_sp': 'meat jerky'} #: data/json/items/comestibles/carnivore.json @@ -68195,13 +68394,13 @@ msgstr "鹽漬的魚乾能夠保存很久, 但是吃了會讓你口渴。" #: data/json/items/comestibles/carnivore.json msgid "smoked meat" msgid_plural "smoked meats" -msgstr[0] "" +msgstr[0] "熏肉" #. ~ Conditional name for smoked meat when FLAG matches CANNIBALISM #: data/json/items/comestibles/carnivore.json msgid "smoked sucker" msgid_plural "smoked sucker" -msgstr[0] "" +msgstr[0] "熏人肉" #. ~ Conditional name for smoked meat when COMPONENT_ID matches mutant #. ~ Conditional name for canned meat when COMPONENT_ID matches mutant @@ -68214,7 +68413,7 @@ msgstr[0] "" #, c-format msgid "%s, mutant" msgid_plural "%s, mutant" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for smoked meat #: data/json/items/comestibles/carnivore.json @@ -68253,7 +68452,7 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "raw liver" msgid_plural "raw livers" -msgstr[0] "" +msgstr[0] "生肝" #. ~ Description for raw liver #: data/json/items/comestibles/carnivore.json @@ -68277,7 +68476,7 @@ msgstr "來自動物的大腦。你不會想生吃它的..." #: data/json/items/comestibles/carnivore.json msgid "raw kidney" msgid_plural "raw kidneys" -msgstr[0] "" +msgstr[0] "生肾" #. ~ Description for raw kidney #: data/json/items/comestibles/carnivore.json @@ -68289,7 +68488,7 @@ msgstr "動物體內的腎臟。 除非你想讓廚房聞到強烈的尿味, #: data/json/items/comestibles/carnivore.json msgid "raw sweetbread" msgid_plural "raw sweetbreads" -msgstr[0] "" +msgstr[0] "生杂碎" #. ~ Description for raw sweetbread #: data/json/items/comestibles/carnivore.json @@ -68314,7 +68513,7 @@ msgstr "血, 應該是人類的。很噁心!" #: data/json/items/comestibles/carnivore.json msgid "bone" msgid_plural "bones" -msgstr[0] "" +msgstr[0] "骨头" #. ~ Description for {'str': 'bone'} #: data/json/items/comestibles/carnivore.json @@ -68338,7 +68537,7 @@ msgstr "屠宰下來的新鮮脂肪。可以生吃, 但是最好還是搭配其 #: data/json/items/comestibles/carnivore.json msgid "tallow" msgid_plural "tallows" -msgstr[0] "" +msgstr[0] "油脂" #. ~ Description for tallow #: data/json/items/comestibles/carnivore.json @@ -68351,7 +68550,7 @@ msgstr "一塊光滑的白色動物脂肪, 經過了清洗和提煉。能夠保 #: data/json/items/comestibles/carnivore.json msgid "lard" msgid_plural "lards" -msgstr[0] "" +msgstr[0] "干油脂" #. ~ Description for lard #: data/json/items/comestibles/carnivore.json @@ -68377,7 +68576,7 @@ msgstr "屠宰变异生物尸体得到的新鲜脂肪,可以用来充饥,但 #: data/json/items/comestibles/carnivore.json msgid "mutant tallow" msgid_plural "mutant tallows" -msgstr[0] "" +msgstr[0] "变异油脂" #. ~ Description for mutant tallow #: data/json/items/comestibles/carnivore.json @@ -68390,7 +68589,7 @@ msgstr "一块清洗后熬制的白色变异生物脂肪。可以保存很久并 #: data/json/items/comestibles/carnivore.json msgid "mutant lard" msgid_plural "mutant lards" -msgstr[0] "" +msgstr[0] "干炼变异油脂" #. ~ Description for mutant lard #: data/json/items/comestibles/carnivore.json @@ -68403,7 +68602,7 @@ msgstr "一块干法炼制的白色变异生物脂肪。可以保存很久并食 #: data/json/items/comestibles/carnivore.json msgid "chunk of mutant humanoid fat" msgid_plural "chunks of mutant humanoid fat" -msgstr[0] "" +msgstr[0] "变异人脂肪块" #. ~ Description for {'str': 'chunk of mutant humanoid fat', 'str_pl': 'chunks #. of mutant humanoid fat'} @@ -68414,7 +68613,7 @@ msgstr "从一只严重变异的人形生物身上切下的肥肉。" #: data/json/items/comestibles/carnivore.json msgid "mutant humanoid tallow" msgid_plural "mutant humanoid tallows" -msgstr[0] "" +msgstr[0] "变异人油" #. ~ Description for mutant humanoid tallow #: data/json/items/comestibles/carnivore.json @@ -68427,7 +68626,7 @@ msgstr "一块清洗后熬制的白色变异人脂肪。可以保存很久并食 #: data/json/items/comestibles/carnivore.json msgid "mutant humanoid lard" msgid_plural "mutant humanoid lards" -msgstr[0] "" +msgstr[0] "干炼变异人油" #. ~ Description for mutant humanoid lard #: data/json/items/comestibles/carnivore.json @@ -68452,7 +68651,7 @@ msgstr "很明顯就能看出是有問題的肉。你能夠吃下, 但是會讓 #: data/json/items/comestibles/carnivore.json msgid "tainted bone" msgid_plural "tainted bones" -msgstr[0] "" +msgstr[0] "被感染的骨头" #. ~ Description for tainted bone #: data/json/items/comestibles/carnivore.json @@ -68477,7 +68676,7 @@ msgstr "一根來自生物的骨頭, 能夠用於製作其他有用的物品… #: data/json/items/comestibles/carnivore.json msgid "tainted fat" msgid_plural "tainted fats" -msgstr[0] "" +msgstr[0] "被感染的脂肪" #. ~ Description for tainted fat #: data/json/items/comestibles/carnivore.json @@ -68489,7 +68688,7 @@ msgstr "一團由變異生物取下的黃色水狀脂肪。你可以吃了它, #: data/json/items/comestibles/carnivore.json msgid "tainted tallow" msgid_plural "tainted tallows" -msgstr[0] "" +msgstr[0] "被感染的油脂" #. ~ Description for tainted tallow #: data/json/items/comestibles/carnivore.json @@ -68502,7 +68701,7 @@ msgstr "一塊光滑的灰色怪物脂肪, 經過了清洗和提煉。能夠長 #: data/json/items/comestibles/carnivore.json msgid "large boiled stomach" msgid_plural "large boiled stomachs" -msgstr[0] "" +msgstr[0] "水煮大胃囊" #. ~ Description for large boiled stomach #: data/json/items/comestibles/carnivore.json @@ -68513,7 +68712,7 @@ msgstr "水煮的動物胃袋, 沒有別的… 看起來不太開胃。" #: data/json/items/comestibles/carnivore.json msgid "boiled large human stomach" msgid_plural "boiled large human stomachs" -msgstr[0] "" +msgstr[0] "水煮大型人胃" #. ~ Description for {'str': 'boiled large human stomach'} #: data/json/items/comestibles/carnivore.json @@ -68525,7 +68724,7 @@ msgstr "水煮的人型生物胃袋, 沒有別的… 看起來不太開胃。" #: data/json/items/comestibles/carnivore.json msgid "boiled stomach" msgid_plural "boiled stomachs" -msgstr[0] "" +msgstr[0] "水煮胃囊" #. ~ Description for {'str': 'boiled stomach'} #: data/json/items/comestibles/carnivore.json @@ -68537,7 +68736,7 @@ msgstr "水煮的小型動物胃袋, 沒有別的… 看起來不太開胃。" #: data/json/items/comestibles/carnivore.json msgid "boiled human stomach" msgid_plural "boiled human stomachs" -msgstr[0] "" +msgstr[0] "水煮人胃" #. ~ Description for {'str': 'boiled human stomach'} #: data/json/items/comestibles/carnivore.json @@ -68549,7 +68748,7 @@ msgstr "水煮的小型人類胃袋, 沒有別的… 看起來不太開胃。" #: data/json/items/comestibles/carnivore.json msgid "raw hide" msgid_plural "raw hides" -msgstr[0] "" +msgstr[0] "生皮" #. ~ Description for raw hide #: data/json/items/comestibles/carnivore.json @@ -68561,7 +68760,7 @@ msgstr "一張細心的從動物身上剝下並折起的生皮。你可以替它 #: data/json/items/comestibles/carnivore.json msgid "tainted hide" msgid_plural "tainted hides" -msgstr[0] "" +msgstr[0] "被感染的生皮" #. ~ Description for tainted hide #: data/json/items/comestibles/carnivore.json @@ -68573,7 +68772,7 @@ msgstr "一張細心的從非自然生物身上剝下並折起的生皮, 有毒 #: data/json/items/comestibles/carnivore.json msgid "raw human skin" msgid_plural "raw human skins" -msgstr[0] "" +msgstr[0] "生人皮" #. ~ Description for raw human skin #: data/json/items/comestibles/carnivore.json @@ -68585,7 +68784,7 @@ msgstr "一張細心的從人類身上剝下並折起的生皮。你可以替它 #: data/json/items/comestibles/carnivore.json msgid "raw pelt" msgid_plural "raw pelts" -msgstr[0] "" +msgstr[0] "生毛皮" #. ~ Description for raw pelt #: data/json/items/comestibles/carnivore.json @@ -68598,7 +68797,7 @@ msgstr "一張細心的從多毛的動物身上剝下並折起的生皮, 它仍 #: data/json/items/comestibles/carnivore.json msgid "tainted pelt" msgid_plural "tainted pelts" -msgstr[0] "" +msgstr[0] "被感染的毛皮" #. ~ Description for tainted pelt #: data/json/items/comestibles/carnivore.json @@ -68611,7 +68810,7 @@ msgstr "一張細心的從多毛的非自然生物身上剝下並折起的生皮 #: data/json/items/comestibles/carnivore.json msgid "raw human pelt" msgid_plural "raw human pelts" -msgstr[0] "" +msgstr[0] "生人毛皮" #. ~ Description for raw human pelt #: data/json/items/comestibles/carnivore.json @@ -68624,7 +68823,7 @@ msgstr "一張細心的從突變長毛的人類身上剝下並折起的生皮, #: data/json/items/comestibles/carnivore.json msgid "seeping heart" msgid_plural "seeping hearts" -msgstr[0] "" +msgstr[0] "渗血心脏" #. ~ Description for seeping heart #: data/json/items/comestibles/carnivore.json @@ -68636,7 +68835,7 @@ msgstr "一團厚厚的肉,看起來像是哺乳動物的心臟,佈滿了許 #: data/json/items/comestibles/carnivore.json msgid "putrid heart" msgid_plural "putrid hearts" -msgstr[0] "" +msgstr[0] "腐化之心" #. ~ Description for putrid heart #: data/json/items/comestibles/carnivore.json @@ -68652,7 +68851,7 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "desiccated putrid heart" msgid_plural "desiccated putrid hearts" -msgstr[0] "" +msgstr[0] "脱水腐化之心" #. ~ Description for desiccated putrid heart #: data/json/items/comestibles/carnivore.json @@ -68665,7 +68864,7 @@ msgstr "一塊巨大的肌肉, 腐爛心臟的所有殘餘, 已被切開並排 #: data/json/items/comestibles/carnivore.json msgid "alien fronds" msgid_plural "alien fronds" -msgstr[0] "" +msgstr[0] "异界蕨叶" #. ~ Description for {'str_sp': 'alien fronds'} #: data/json/items/comestibles/carnivore.json @@ -68679,7 +68878,7 @@ msgstr "" #: data/json/items/comestibles/carnivore.json msgid "leech flower" msgid_plural "leech flowers" -msgstr[0] "" +msgstr[0] "水蛭花" #. ~ Use action activation_message for leech flower. #: data/json/items/comestibles/carnivore.json @@ -68748,7 +68947,7 @@ msgstr "在裝罐之前已經除去約60%水份的牛奶。" #: data/json/items/comestibles/dairy.json msgid "yogurt" msgid_plural "yogurts" -msgstr[0] "" +msgstr[0] "酸奶" #. ~ Description for yogurt #: data/json/items/comestibles/dairy.json @@ -68781,7 +68980,7 @@ msgstr "去雜質的奶油,不含乳固體和水。能保存很長的時間。 #: data/json/items/comestibles/dairy.json msgid "pudding" msgid_plural "puddings" -msgstr[0] "" +msgstr[0] "布丁" #. ~ Description for pudding #: data/json/items/comestibles/dairy.json @@ -68791,7 +68990,7 @@ msgstr "含糖乳製品。一種美妙享受的代名詞。" #: data/json/items/comestibles/dairy.json msgid "fresh cheese" msgid_plural "fresh cheese" -msgstr[0] "" +msgstr[0] "鲜奶酪" #. ~ Description for {'str_sp': 'fresh cheese'} #: data/json/items/comestibles/dairy.json @@ -68826,7 +69025,7 @@ msgstr "一塊處理過的黃橙橙起司。" #: data/json/items/comestibles/dairy.json msgid "quesadilla" msgid_plural "quesadillas" -msgstr[0] "" +msgstr[0] "起司薄饼" #. ~ Description for quesadilla #: data/json/items/comestibles/dairy.json @@ -68868,7 +69067,7 @@ msgstr "由新鮮的蘋果壓榨而成, 新鮮又美味。" #: data/json/items/comestibles/drink.json msgid "almond milk" msgid_plural "almond milks" -msgstr[0] "" +msgstr[0] "扁桃仁乳" #. ~ Description for {'str': 'almond milk'} #: data/json/items/comestibles/drink.json @@ -68880,7 +69079,7 @@ msgstr "從扁桃仁擠奶?不是的,但可以將它們與水混合,是的 #: data/json/items/comestibles/drink.json msgid "soy milk" msgid_plural "soy milks" -msgstr[0] "" +msgstr[0] "豆乳" #. ~ Description for soy milk #: data/json/items/comestibles/drink.json @@ -68930,7 +69129,7 @@ msgstr "一種健康的飲品, 把管蜂香草以沸水沖泡而成。可用於 #: data/json/items/comestibles/drink.json msgid "coconut milk" msgid_plural "coconut milks" -msgstr[0] "" +msgstr[0] "椰子奶" #. ~ Description for coconut milk #: data/json/items/comestibles/drink.json @@ -68962,7 +69161,7 @@ msgstr "由洋甘菊花浸泡在沸水中製成的健康飲料。可用於治療 #: data/json/items/comestibles/drink.json msgid "chocolate drink" msgid_plural "chocolate drinks" -msgstr[0] "" +msgstr[0] "巧克力饮料" #. ~ Description for chocolate drink #: data/json/items/comestibles/drink.json @@ -68999,7 +69198,7 @@ msgstr "将经过烘烤的菊苣根,浸泡在沸水中。这种苦酿被用作 #: data/json/items/comestibles/drink.json msgid "dark cola" msgid_plural "dark colas" -msgstr[0] "" +msgstr[0] "可乐" #. ~ Description for dark cola #: data/json/items/comestibles/drink.json @@ -69009,7 +69208,7 @@ msgstr "有可樂喝總是幸福些。內含糖水與咖啡因。" #: data/json/items/comestibles/drink.json msgid "energy cola" msgid_plural "energy colas" -msgstr[0] "" +msgstr[0] "能量可乐" #. ~ Description for energy cola #: data/json/items/comestibles/drink.json @@ -69021,7 +69220,7 @@ msgstr "它的味道嘗起來像玻璃穩潔, 但是加了滿滿的糖與咖啡 #: data/json/items/comestibles/drink.json msgid "cream soda" msgid_plural "cream sodas" -msgstr[0] "" +msgstr[0] "奶油汽水" #. ~ Description for cream soda #: data/json/items/comestibles/drink.json @@ -69031,7 +69230,7 @@ msgstr "一杯含咖啡因的碳酸飲料, 香草口味。" #: data/json/items/comestibles/drink.json msgid "cranberry juice" msgid_plural "cranberry juices" -msgstr[0] "" +msgstr[0] "蔓越莓果汁" #. ~ Description for cranberry juice #: data/json/items/comestibles/drink.json @@ -69062,7 +69261,7 @@ msgstr "一種健康的飲料, 將蒲公英的根浸泡在開水之中而成。" #: data/json/items/comestibles/drink.json msgid "dandelion and burdock tea" msgid_plural "dandelion and burdock tea" -msgstr[0] "" +msgstr[0] "蒲公英牛蒡茶" #. ~ Description for {'str_sp': 'dandelion and burdock tea'} #: data/json/items/comestibles/drink.json @@ -69074,7 +69273,7 @@ msgstr "有助健康的草药汤,把蒲公英和牛蒡根放入沸水中煮烂 #: data/json/items/comestibles/drink.json msgid "eggnog" msgid_plural "eggnogs" -msgstr[0] "" +msgstr[0] "蛋诺" #. ~ Description for eggnog #: data/json/items/comestibles/drink.json @@ -69088,7 +69287,7 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "energy drink" msgid_plural "energy drinks" -msgstr[0] "" +msgstr[0] "能量饮料" #. ~ Description for energy drink #: data/json/items/comestibles/drink.json @@ -69100,7 +69299,7 @@ msgstr "一種含有大量咖啡因的汽水。能量飲料在需要熬夜工作 #: data/json/items/comestibles/drink.json msgid "atomic energy drink" msgid_plural "atomic energy drinks" -msgstr[0] "" +msgstr[0] "原子能量饮料" #. ~ Description for {'str': 'atomic energy drink'} #: data/json/items/comestibles/drink.json @@ -69136,7 +69335,7 @@ msgstr "也被稱為熱可可, 這種熱巧克力在寒冷的冬日是完美的 #: data/json/items/comestibles/drink.json msgid "fruit juice" msgid_plural "fruit juices" -msgstr[0] "" +msgstr[0] "果汁" #. ~ Description for fruit juice #: data/json/items/comestibles/drink.json @@ -69146,7 +69345,7 @@ msgstr "從真的水果新鮮壓榨出的果汁! 好喝又營養。" #: data/json/items/comestibles/drink.json msgid "kompot" msgid_plural "kompots" -msgstr[0] "" +msgstr[0] "糖水果肉" #. ~ Description for kompot #: data/json/items/comestibles/drink.json @@ -69170,7 +69369,7 @@ msgstr "混合了水與糖以緩和其酸味的檸檬汁, 美味又提神。" #: data/json/items/comestibles/drink.json msgid "lemon-lime soda" msgid_plural "lemon-lime sodas" -msgstr[0] "" +msgstr[0] "柠檬汽水" #. ~ Description for lemon-lime soda #: data/json/items/comestibles/drink.json @@ -69182,7 +69381,7 @@ msgstr "與可樂相比, 這飲料不含咖啡因, 然而還是加入了碳酸 #: data/json/items/comestibles/drink.json msgid "lotus tea" msgid_plural "lotus tea" -msgstr[0] "" +msgstr[0] "荷花茶" #. ~ Description for {'str_sp': 'lotus tea'} #: data/json/items/comestibles/drink.json @@ -69221,7 +69420,7 @@ msgstr "牛犢的食物,適合成人食用。該牛奶是從加工過的牛奶 #: data/json/items/comestibles/drink.json msgid "coffee milk" msgid_plural "coffee milks" -msgstr[0] "" +msgstr[0] "牛奶咖啡" #. ~ Description for coffee milk #: data/json/items/comestibles/drink.json @@ -69231,7 +69430,7 @@ msgstr "一份加了牛奶的咖啡。" #: data/json/items/comestibles/drink.json msgid "sweet atomic coffee" msgid_plural "sweet atomic coffee" -msgstr[0] "" +msgstr[0] "甜原子咖啡" #. ~ Description for {'str_sp': 'sweet atomic coffee'} #: data/json/items/comestibles/drink.json @@ -69243,7 +69442,7 @@ msgstr "加牛奶的原子咖啡。用原子咖啡机的\"核动力全开\"模 #: data/json/items/comestibles/drink.json msgid "milk tea" msgid_plural "milk teas" -msgstr[0] "" +msgstr[0] "奶茶" #. ~ Description for milk tea #: data/json/items/comestibles/drink.json @@ -69253,7 +69452,7 @@ msgstr "熱茶加入冷牛奶。" #: data/json/items/comestibles/drink.json msgid "orange juice" msgid_plural "orange juices" -msgstr[0] "" +msgstr[0] "橙汁" #. ~ Description for orange juice #: data/json/items/comestibles/drink.json @@ -69263,7 +69462,7 @@ msgstr "從真的橘子新鮮壓榨出的果汁! 好喝又營養。" #: data/json/items/comestibles/drink.json msgid "orange soda" msgid_plural "orange sodas" -msgstr[0] "" +msgstr[0] "橙子汽水" #. ~ Description for orange soda #: data/json/items/comestibles/drink.json @@ -69287,7 +69486,7 @@ msgstr "一種芬芳的健康飲品, 把松葉以沸水沖泡而成。" #: data/json/items/comestibles/drink.json msgid "grape drink" msgid_plural "grape drinks" -msgstr[0] "" +msgstr[0] "葡萄汽水" #. ~ Description for grape drink #: data/json/items/comestibles/drink.json @@ -69310,7 +69509,7 @@ msgstr "像可樂但是不含咖啡因, 一樣對身體不好。" #: data/json/items/comestibles/drink.json msgid "spezi" msgid_plural "spezis" -msgstr[0] "" +msgstr[0] "柏林汽水" #. ~ Description for spezi #: data/json/items/comestibles/drink.json @@ -69322,7 +69521,7 @@ msgstr "原產於德國近一個世紀前, 這樣搭配可樂和橘子汽水的 #: data/json/items/comestibles/drink.json msgid "sports drink" msgid_plural "sports drinks" -msgstr[0] "" +msgstr[0] "运动饮料" #. ~ Description for sports drink #: data/json/items/comestibles/drink.json @@ -69335,7 +69534,7 @@ msgstr "一種融合了電解質與單醣的特殊飲料, 喝起來像是瓶裝 #: data/json/items/comestibles/drink.json msgid "spurge tea" msgid_plural "spurge tea" -msgstr[0] "" +msgstr[0] "大戟花茶" #. ~ Description for {'str_sp': 'spurge tea'} #: data/json/items/comestibles/drink.json @@ -69347,7 +69546,7 @@ msgstr "有助健康的草药汤,把大戟花放入沸水中煮烂制成。可 #: data/json/items/comestibles/drink.json msgid "rehydration drink" msgid_plural "rehydration drinks" -msgstr[0] "" +msgstr[0] "补液饮料" #. ~ Description for rehydration drink #: data/json/items/comestibles/drink.json @@ -69369,7 +69568,7 @@ msgstr "添加了糖或蜂蜜的水。味道也就還好。" #: data/json/items/comestibles/drink.json msgid "tea" msgid_plural "teas" -msgstr[0] "" +msgstr[0] "茶" #. ~ Description for tea #: data/json/items/comestibles/drink.json @@ -69381,7 +69580,7 @@ msgstr "供全球每位紳士享用的飲品,以熱水沖泡茶樹的葉子製 #: data/json/items/comestibles/drink.json msgid "bark tea" msgid_plural "bark teas" -msgstr[0] "" +msgstr[0] "树皮茶" #. ~ Description for {'str': 'bark tea'} #: data/json/items/comestibles/drink.json @@ -69393,7 +69592,7 @@ msgstr "在一些國家通常被視為民間藥方, 味很道糟糕且會讓你 #: data/json/items/comestibles/drink.json msgid "V8" msgid_plural "V8s" -msgstr[0] "" +msgstr[0] "V8蔬菜汁" #. ~ Description for {'str': 'V8'} #: data/json/items/comestibles/drink.json @@ -69430,7 +69629,7 @@ msgstr "優質的礦泉水, 太優質了讓你連拿著瓶子都覺得優質。" #: data/json/items/comestibles/drink.json msgid "sweet coffee" msgid_plural "sweet coffees" -msgstr[0] "" +msgstr[0] "甜咖啡" #. ~ Description for {'str': 'sweet coffee'} #: data/json/items/comestibles/drink.json @@ -69445,7 +69644,7 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "sweet tea" msgid_plural "sweet teas" -msgstr[0] "" +msgstr[0] "甜茶" #. ~ Description for {'str': 'sweet tea'} #: data/json/items/comestibles/drink.json @@ -69457,7 +69656,7 @@ msgstr "一份供全球绅士享用的饮品,通过将滚烫的开水倒入被 #: data/json/items/comestibles/drink.json msgid "sweet milk tea" msgid_plural "sweet milk teas" -msgstr[0] "" +msgstr[0] "甜奶茶" #. ~ Description for {'str': 'sweet milk tea'} #: data/json/items/comestibles/drink.json @@ -69467,7 +69666,7 @@ msgstr "一份热茶,加入了冷牛奶和甜味剂。" #: data/json/items/comestibles/drink.json msgid "sweet coffee substitute" msgid_plural "sweet coffee substitutes" -msgstr[0] "" +msgstr[0] "甜咖啡代用品" #. ~ Description for {'str': 'sweet coffee substitute'} #: data/json/items/comestibles/drink.json @@ -69482,7 +69681,7 @@ msgstr "" #: data/json/items/comestibles/drink.json msgid "sweet coffee milk" msgid_plural "sweet coffee milks" -msgstr[0] "" +msgstr[0] "甜牛奶咖啡" #. ~ Description for {'str': 'sweet coffee milk'} #: data/json/items/comestibles/drink.json @@ -69492,7 +69691,7 @@ msgstr "一份加了牛奶的咖啡。为爱吃甜食的人加了一些甜味剂 #: data/json/items/comestibles/drink.json msgid "sweet atomic coffee milk" msgid_plural "sweet atomic coffee milks" -msgstr[0] "" +msgstr[0] "甜原子咖啡牛奶" #. ~ Description for {'str': 'sweet atomic coffee milk'} #: data/json/items/comestibles/drink.json @@ -69514,7 +69713,7 @@ msgstr "一份用原子咖啡机的\"核动力全开\"模式煮成的咖啡。 #: data/json/items/comestibles/drink_other.json msgid "red sauce" msgid_plural "red sauces" -msgstr[0] "" +msgstr[0] "番茄沙司" #. ~ Description for red sauce #: data/json/items/comestibles/drink_other.json @@ -69546,7 +69745,7 @@ msgstr "一種由雞蛋,油和鹽的混合物,傳統上用來滋潤三明治 #: data/json/items/comestibles/drink_other.json msgid "ketchup" msgid_plural "ketchups" -msgstr[0] "" +msgstr[0] "番茄酱" #. ~ Description for ketchup #: data/json/items/comestibles/drink_other.json @@ -69575,7 +69774,7 @@ msgstr "蜂蜜, 蜜蜂的產物。這是 \"森林蜜\", 一種液態的蜂蜜。 #: data/json/items/comestibles/drink_other.json msgid "peanut butter" msgid_plural "peanut butters" -msgstr[0] "" +msgstr[0] "花生酱" #. ~ Description for peanut butter #: data/json/items/comestibles/drink_other.json @@ -69587,7 +69786,7 @@ msgstr "棕色的黏稠物, 吃起來就像它的名字。不難吃, 但是它 #: data/json/items/comestibles/drink_other.json msgid "imitation peanutbutter" msgid_plural "imitation peanutbutters" -msgstr[0] "" +msgstr[0] "代花生酱" #. ~ Description for imitation peanutbutter #: data/json/items/comestibles/drink_other.json @@ -69664,7 +69863,7 @@ msgstr "水和糖與濃縮咖啡製成的濃厚糖漿。可用於許多食品和 #: data/json/items/comestibles/egg.json msgid "bird egg" msgid_plural "bird eggs" -msgstr[0] "" +msgstr[0] "鸟蛋" #. ~ Description for {'str': 'bird egg'} #: data/json/items/comestibles/egg.json @@ -69674,12 +69873,12 @@ msgstr "由鳥生下的蛋, 很營養。" #: data/json/items/comestibles/egg.json msgid "chicken egg" msgid_plural "chicken eggs" -msgstr[0] "" +msgstr[0] "鸡蛋" #: data/json/items/comestibles/egg.json msgid "unfertilized bird egg" msgid_plural "unfertilized bird eggs" -msgstr[0] "" +msgstr[0] "鸟蛋(未受精)" #. ~ Description for {'str': 'unfertilized bird egg'} #: data/json/items/comestibles/egg.json @@ -69691,42 +69890,42 @@ msgstr "一枚由禽类下的营养丰富的蛋。这枚蛋还未受精,可能 #: data/json/items/comestibles/egg.json msgid "grouse egg" msgid_plural "grouse eggs" -msgstr[0] "" +msgstr[0] "松鸡蛋" #: data/json/items/comestibles/egg.json msgid "crow egg" msgid_plural "crow eggs" -msgstr[0] "" +msgstr[0] "乌鸦蛋" #: data/json/items/comestibles/egg.json msgid "duck egg" msgid_plural "duck eggs" -msgstr[0] "" +msgstr[0] "鸭蛋" #: data/json/items/comestibles/egg.json msgid "goose egg" msgid_plural "goose eggs" -msgstr[0] "" +msgstr[0] "雁卵" #: data/json/items/comestibles/egg.json msgid "turkey egg" msgid_plural "turkey eggs" -msgstr[0] "" +msgstr[0] "火鸡蛋" #: data/json/items/comestibles/egg.json msgid "pheasant egg" msgid_plural "pheasant eggs" -msgstr[0] "" +msgstr[0] "雉鸡蛋" #: data/json/items/comestibles/egg.json msgid "cockatrice egg" msgid_plural "cockatrice eggs" -msgstr[0] "" +msgstr[0] "鸡蛇怪卵" #: data/json/items/comestibles/egg.json msgid "reptile egg" msgid_plural "reptile eggs" -msgstr[0] "" +msgstr[0] "爬虫蛋" #. ~ Description for reptile egg #: data/json/items/comestibles/egg.json @@ -69736,7 +69935,7 @@ msgstr "築巢在新英格蘭地區的某種爬行動物的蛋。" #: data/json/items/comestibles/egg.json msgid "ant egg" msgid_plural "ant eggs" -msgstr[0] "" +msgstr[0] "蚁卵" #. ~ Description for {'str': 'ant egg'} #: data/json/items/comestibles/egg.json @@ -69748,7 +69947,7 @@ msgstr "一顆跟壘球一樣大的白色螞蟻蛋。含有豐富的營養, 但 #: data/json/items/comestibles/egg.json msgid "spider egg" msgid_plural "spider eggs" -msgstr[0] "" +msgstr[0] "蜘蛛卵" #. ~ Description for spider egg #: data/json/items/comestibles/egg.json @@ -69760,7 +69959,7 @@ msgstr "一只巨型蜘蛛的蛋,比鸡蛋大一点。看起来十分恶心。 #: data/json/items/comestibles/egg.json msgid "roach egg" msgid_plural "roach eggs" -msgstr[0] "" +msgstr[0] "蟑螂卵" #. ~ Description for roach egg #: data/json/items/comestibles/egg.json @@ -69772,7 +69971,7 @@ msgstr "一只巨型蟑螂的蛋,比鸡蛋大一点。看起来十分恶心。 #: data/json/items/comestibles/egg.json msgid "insect egg" msgid_plural "insect eggs" -msgstr[0] "" +msgstr[0] "虫卵" #. ~ Description for insect egg #: data/json/items/comestibles/egg.json @@ -69782,7 +69981,7 @@ msgstr "一只蝗虫生的蛋,比鸡蛋大一点。" #: data/json/items/comestibles/egg.json msgid "razorclaw roe" msgid_plural "razorclaw roes" -msgstr[0] "" +msgstr[0] "利爪怪卵" #. ~ Description for razorclaw roe #: data/json/items/comestibles/egg.json @@ -69794,7 +69993,7 @@ msgstr "" #: data/json/items/comestibles/egg.json msgid "roe" msgid_plural "roes" -msgstr[0] "" +msgstr[0] "鱼卵" #. ~ Description for roe #: data/json/items/comestibles/egg.json @@ -69804,7 +70003,7 @@ msgstr "未知魚類產的普通魚卵。" #: data/json/items/comestibles/egg.json msgid "powdered egg" msgid_plural "powdered eggs" -msgstr[0] "" +msgstr[0] "干燥全蛋粉" #. ~ Description for {'str': 'powdered egg'} #: data/json/items/comestibles/egg.json @@ -69824,7 +70023,7 @@ msgstr "蓬鬆可口的炒蛋。" #: data/json/items/comestibles/egg.json msgid "boiled egg" msgid_plural "boiled eggs" -msgstr[0] "" +msgstr[0] "煮蛋" #. ~ Description for {'str': 'boiled egg'} #: data/json/items/comestibles/egg.json @@ -69834,7 +70033,7 @@ msgstr "一只白煮蛋,壳都没有剥掉。营养全面又便于携带。" #: data/json/items/comestibles/egg.json msgid "pickled egg" msgid_plural "pickled eggs" -msgstr[0] "" +msgstr[0] "腌蛋" #. ~ Description for pickled egg #: data/json/items/comestibles/egg.json @@ -69842,10 +70041,50 @@ msgid "" "A pickled egg. Rather salty, but tastes good and lasts for a long time." msgstr "醃蛋。非常酸, 但很美味, 而且能夠保存很久。" +#: data/json/items/comestibles/egg.json +msgid "salsify omelette" +msgid_plural "salsify omelette" +msgstr[0] "蒜叶婆罗门参欧姆蛋" + +#. ~ Description for {'str_sp': 'salsify omelette'} +#: data/json/items/comestibles/egg.json +msgid "A salsify omelette." +msgstr "一个蒜叶婆罗门参欧姆蛋。" + +#: data/json/items/comestibles/egg.json +msgid "wild veggetable omelette" +msgid_plural "wild veggetable omelette" +msgstr[0] "野菜欧姆蛋" + +#. ~ Description for {'str_sp': 'wild veggetable omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with wild vegetables." +msgstr "一个用野菜制作的欧姆蛋。" + +#: data/json/items/comestibles/egg.json +msgid "mushroom omelette" +msgid_plural "mushroom omelette" +msgstr[0] "蘑菇欧姆蛋" + +#. ~ Description for {'str_sp': 'mushroom omelette'} +#: data/json/items/comestibles/egg.json +msgid "An omelette made with mushrooms." +msgstr "一个用蘑菇制作的欧姆蛋。" + +#: data/json/items/comestibles/egg.json +msgid "spanish omelette" +msgid_plural "spanish omelette" +msgstr[0] "西班牙欧姆蛋" + +#. ~ Description for {'str_sp': 'spanish omelette'} +#: data/json/items/comestibles/egg.json +msgid "A spanish omelette." +msgstr "一个西班牙欧姆蛋。" + #: data/json/items/comestibles/frozen.json msgid "milkshake" msgid_plural "milkshakes" -msgstr[0] "" +msgstr[0] "奶昔" #. ~ Description for {'str': 'milkshake'} #: data/json/items/comestibles/frozen.json @@ -69869,7 +70108,7 @@ msgstr "通過冷凍預製混合物製成的奶昔。加了越多糖會更好吃 #: data/json/items/comestibles/frozen.json msgid "deluxe milkshake" msgid_plural "deluxe milkshakes" -msgstr[0] "" +msgstr[0] "豪华奶昔" #. ~ Description for {'str': 'deluxe milkshake'} #: data/json/items/comestibles/frozen.json @@ -69989,7 +70228,7 @@ msgstr "它有點像草莓果醬, 只是沒有加糖。" #: data/json/items/comestibles/fruit_dishes.json msgid "fruit leather" msgid_plural "fruit leathers" -msgstr[0] "" +msgstr[0] "果丹皮" #. ~ Description for fruit leather #: data/json/items/comestibles/fruit_dishes.json @@ -70020,7 +70259,7 @@ msgstr "黃色的水蜜桃片, 浸泡在糖水當中。" #: data/json/items/comestibles/fruit_dishes.json msgid "canned pineapple" msgid_plural "canned pineapples" -msgstr[0] "" +msgstr[0] "罐装菠萝" #. ~ Description for canned pineapple #: data/json/items/comestibles/fruit_dishes.json @@ -70042,7 +70281,7 @@ msgstr "帶有強烈檸檬氣味的黃色粉末。能與水混合作出檸檬水 #: data/json/items/comestibles/fruit_dishes.json msgid "cooked fruit" msgid_plural "cooked fruits" -msgstr[0] "" +msgstr[0] "煮水果" #. ~ Description for cooked fruit #: data/json/items/comestibles/fruit_dishes.json @@ -70052,7 +70291,7 @@ msgstr "它有點像果醬, 只是沒有加糖。" #: data/json/items/comestibles/fruit_dishes.json msgid "fruit jam" msgid_plural "fruit jams" -msgstr[0] "" +msgstr[0] "果酱" #. ~ Description for fruit jam #: data/json/items/comestibles/fruit_dishes.json @@ -70087,7 +70326,7 @@ msgstr "沖調過的脫水水果乾, 重新加了水之後讓這東西變得更 #: data/json/items/comestibles/fruit_dishes.json msgid "fruit slice" msgid_plural "fruit slices" -msgstr[0] "" +msgstr[0] "糖渍水果片" #. ~ Description for {'str': 'fruit slice'} #: data/json/items/comestibles/fruit_dishes.json @@ -70213,7 +70452,7 @@ msgstr "被輻射照過的藍莓, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated apple" msgid_plural "irradiated apples" -msgstr[0] "" +msgstr[0] "辐照苹果" #. ~ Description for irradiated apple #: data/json/items/comestibles/irradiated_fruit.json @@ -70225,7 +70464,7 @@ msgstr "嗯, 被輻射照過。能夠保存到近乎永遠。經過輻射消毒, #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated banana" msgid_plural "irradiated bananas" -msgstr[0] "" +msgstr[0] "辐照香蕉" #. ~ Description for irradiated banana #: data/json/items/comestibles/irradiated_fruit.json @@ -70237,7 +70476,7 @@ msgstr "被輻射照過的香蕉, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated orange" msgid_plural "irradiated oranges" -msgstr[0] "" +msgstr[0] "辐照橘子" #. ~ Description for irradiated orange #: data/json/items/comestibles/irradiated_fruit.json @@ -70249,7 +70488,7 @@ msgstr "被輻射照過的柳橙, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated lemon" msgid_plural "irradiated lemons" -msgstr[0] "" +msgstr[0] "辐照柠檬" #. ~ Description for irradiated lemon #: data/json/items/comestibles/irradiated_fruit.json @@ -70261,7 +70500,7 @@ msgstr "被輻射照過的檸檬, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated grapefruit" msgid_plural "irradiated grapefruits" -msgstr[0] "" +msgstr[0] "辐照西柚" #. ~ Description for irradiated grapefruit #: data/json/items/comestibles/irradiated_fruit.json @@ -70273,7 +70512,7 @@ msgstr "被輻射照過的葡萄柚, 能夠保存到近乎永遠。經過輻射 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated pear" msgid_plural "irradiated pears" -msgstr[0] "" +msgstr[0] "辐照梨子" #. ~ Description for irradiated pear #: data/json/items/comestibles/irradiated_fruit.json @@ -70298,7 +70537,7 @@ msgstr "被輻射照過的櫻桃, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated plum" msgid_plural "irradiated plums" -msgstr[0] "" +msgstr[0] "辐照李子" #. ~ Description for irradiated plum #: data/json/items/comestibles/irradiated_fruit.json @@ -70310,7 +70549,7 @@ msgstr "被輻射照過的一串李子, 能夠保存到近乎永遠。經過輻 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated grape" msgid_plural "irradiated grapes" -msgstr[0] "" +msgstr[0] "辐照葡萄" #. ~ Description for {'str': 'irradiated grape'} #: data/json/items/comestibles/irradiated_fruit.json @@ -70322,7 +70561,7 @@ msgstr "被輻射照過的葡萄, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated pineapple" msgid_plural "irradiated pineapples" -msgstr[0] "" +msgstr[0] "辐照菠萝" #. ~ Description for irradiated pineapple #: data/json/items/comestibles/irradiated_fruit.json @@ -70347,7 +70586,7 @@ msgstr "被輻射照過的桃子, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated watermelon" msgid_plural "irradiated watermelons" -msgstr[0] "" +msgstr[0] "辐照西瓜" #. ~ Description for irradiated watermelon #: data/json/items/comestibles/irradiated_fruit.json @@ -70359,7 +70598,7 @@ msgstr "被輻射照過的西瓜, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated melon" msgid_plural "irradiated melons" -msgstr[0] "" +msgstr[0] "辐照香瓜" #. ~ Description for irradiated melon #: data/json/items/comestibles/irradiated_fruit.json @@ -70384,7 +70623,7 @@ msgstr "被輻射照過的黑莓, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated mango" msgid_plural "irradiated mangos" -msgstr[0] "" +msgstr[0] "辐照芒果" #. ~ Description for irradiated mango #: data/json/items/comestibles/irradiated_fruit.json @@ -70396,7 +70635,7 @@ msgstr "被輻射照過的芒果, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated pomegranate" msgid_plural "irradiated pomegranates" -msgstr[0] "" +msgstr[0] "辐照石榴" #. ~ Description for irradiated pomegranate #: data/json/items/comestibles/irradiated_fruit.json @@ -70408,7 +70647,7 @@ msgstr "被輻射照過的石榴, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated papaya" msgid_plural "irradiated papayas" -msgstr[0] "" +msgstr[0] "辐照木瓜" #. ~ Description for irradiated papaya #: data/json/items/comestibles/irradiated_fruit.json @@ -70420,7 +70659,7 @@ msgstr "被輻射照過的木瓜, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated kiwi" msgid_plural "irradiated kiwis" -msgstr[0] "" +msgstr[0] "辐照猕猴桃" #. ~ Description for irradiated kiwi #: data/json/items/comestibles/irradiated_fruit.json @@ -70432,7 +70671,7 @@ msgstr "被輻射照過的奇異果, 能夠保存到近乎永遠。經過輻射 #: data/json/items/comestibles/irradiated_fruit.json msgid "irradiated apricot" msgid_plural "irradiated apricots" -msgstr[0] "" +msgstr[0] "辐照杏子" #. ~ Description for irradiated apricot #: data/json/items/comestibles/irradiated_fruit.json @@ -70444,7 +70683,7 @@ msgstr "被輻射照過的杏子, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated lettuce" msgid_plural "irradiated lettuces" -msgstr[0] "" +msgstr[0] "辐照莴苣" #. ~ Description for irradiated lettuce #: data/json/items/comestibles/irradiated_veggy.json @@ -70456,7 +70695,7 @@ msgstr "被輻射照過的萵苣, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated cabbage" msgid_plural "irradiated cabbages" -msgstr[0] "" +msgstr[0] "辐照卷心菜" #. ~ Description for irradiated cabbage #: data/json/items/comestibles/irradiated_veggy.json @@ -70493,7 +70732,7 @@ msgstr "被輻射照過的花椰菜, 能夠保存到近乎永遠。經過輻射 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated zucchini" msgid_plural "irradiated zucchinis" -msgstr[0] "" +msgstr[0] "辐照西葫芦" #. ~ Description for irradiated zucchini #: data/json/items/comestibles/irradiated_veggy.json @@ -70505,7 +70744,7 @@ msgstr "被輻射照過的西葫蘆, 能夠保存到近乎永遠。經過輻射 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated onion" msgid_plural "irradiated onions" -msgstr[0] "" +msgstr[0] "辐照洋葱" #. ~ Description for irradiated onion #: data/json/items/comestibles/irradiated_veggy.json @@ -70517,7 +70756,7 @@ msgstr "被輻射照過的洋蔥, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated carrot" msgid_plural "irradiated carrots" -msgstr[0] "" +msgstr[0] "辐照胡萝卜" #. ~ Description for irradiated carrot #: data/json/items/comestibles/irradiated_veggy.json @@ -70541,7 +70780,7 @@ msgstr "被輻射照過的玉米, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated pumpkin" msgid_plural "irradiated pumpkins" -msgstr[0] "" +msgstr[0] "辐照南瓜" #. ~ Description for irradiated pumpkin #: data/json/items/comestibles/irradiated_veggy.json @@ -70566,7 +70805,7 @@ msgstr "被輻射照過的馬鈴薯, 能夠保存到近乎永遠。經過輻射 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated cucumber" msgid_plural "irradiated cucumbers" -msgstr[0] "" +msgstr[0] "辐照黄瓜" #. ~ Description for irradiated cucumber #: data/json/items/comestibles/irradiated_veggy.json @@ -70578,7 +70817,7 @@ msgstr "被輻射照過的黃瓜, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated celery" msgid_plural "irradiated celerys" -msgstr[0] "" +msgstr[0] "辐照芹菜" #. ~ Description for irradiated celery #: data/json/items/comestibles/irradiated_veggy.json @@ -70590,7 +70829,7 @@ msgstr "被輻射照過的芹菜, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/irradiated_veggy.json msgid "irradiated rhubarb" msgid_plural "irradiated rhubarbs" -msgstr[0] "" +msgstr[0] "辐射大黄" #. ~ Description for irradiated rhubarb #: data/json/items/comestibles/irradiated_veggy.json @@ -70602,7 +70841,7 @@ msgstr "被輻射照過的大黃, 能夠保存到近乎永遠。經過輻射消 #: data/json/items/comestibles/junkfood.json msgid "toast-em" msgid_plural "toast-ems" -msgstr[0] "" +msgstr[0] "托姆果塔饼干" #. ~ Description for toast-em #: data/json/items/comestibles/junkfood.json @@ -70723,7 +70962,7 @@ msgstr "一種鹹口味的零食。" #: data/json/items/comestibles/junkfood.json msgid "chocolate-covered pretzel" msgid_plural "chocolate-covered pretzels" -msgstr[0] "" +msgstr[0] "巧克力椒盐脆饼干" #. ~ Description for chocolate-covered pretzel #: data/json/items/comestibles/junkfood.json @@ -70733,7 +70972,7 @@ msgstr "一種鹹口味的零食, 包覆著巧克力。" #: data/json/items/comestibles/junkfood.json msgid "chocolate bar" msgid_plural "chocolate bars" -msgstr[0] "" +msgstr[0] "巧克力棒" #. ~ Description for chocolate bar #: data/json/items/comestibles/junkfood.json @@ -70789,7 +71028,7 @@ msgstr "一把五顏六色的巧克力夾心糖。" #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json msgid "chewy candy" msgid_plural "chewy candy" -msgstr[0] "" +msgstr[0] "软糖" #. ~ Description for {'str_sp': 'chewy candy'} #: data/json/items/comestibles/junkfood.json @@ -70824,7 +71063,7 @@ msgstr "這個金色、半透明薄片糖果是由純楓糖漿製成, 吃起來 #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json msgid "graham cracker" msgid_plural "graham crackers" -msgstr[0] "" +msgstr[0] "全麦饼干" #. ~ Description for graham cracker #: data/json/items/comestibles/junkfood.json @@ -70836,9 +71075,10 @@ msgstr "乾燥的含糖餅乾, 會讓你感到非常口渴, 但至少它比巧 #: data/json/items/comestibles/junkfood.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cookie" msgid_plural "cookies" -msgstr[0] "" +msgstr[0] "曲奇饼" #. ~ Description for cookie #: data/json/items/comestibles/junkfood.json @@ -70872,7 +71112,7 @@ msgstr "用碎甜菜製作的濃糖漿。在烹飪時是種很好的甜味劑。 #: data/json/items/comestibles/junkfood.json msgid "cake" msgid_plural "cakes" -msgstr[0] "" +msgstr[0] "蛋糕" #. ~ Description for cake #: data/json/items/comestibles/junkfood.json @@ -70895,7 +71135,7 @@ msgstr "裹滿了你從沒看過的厚厚糖衣。有人在蛋糕上面寫了瘋 #: data/json/items/comestibles/junkfood.json msgid "chocolate-covered coffee bean" msgid_plural "chocolate-covered coffee beans" -msgstr[0] "" +msgstr[0] "巧克力咖啡豆" #. ~ Description for chocolate-covered coffee bean #: data/json/items/comestibles/junkfood.json @@ -70938,7 +71178,7 @@ msgstr "一把覆蓋巧克力的軟薄荷餡餅… 味道好極了!" #: data/json/items/comestibles/junkfood.json msgid "Necco wafers" msgid_plural "Necco wafers" -msgstr[0] "" +msgstr[0] "彩虹糖" #. ~ Description for {'str_sp': 'Necco wafers'} #: data/json/items/comestibles/junkfood.json @@ -70950,7 +71190,7 @@ msgstr "一大袋的糖果, 有多種口味: 柳橙、檸檬、青檸、丁香 #: data/json/items/comestibles/junkfood.json msgid "candy cigarette" msgid_plural "candy cigarettes" -msgstr[0] "" +msgstr[0] "香烟糖" #. ~ Description for candy cigarette #: data/json/items/comestibles/junkfood.json @@ -70977,7 +71217,7 @@ msgstr "我賭你絕對停不下來。" #: data/json/items/comestibles/junkfood.json msgid "sugary cereal" msgid_plural "sugary cereals" -msgstr[0] "" +msgstr[0] "早餐麦片" #. ~ Description for sugary cereal #: data/json/items/comestibles/junkfood.json @@ -70989,7 +71229,7 @@ msgstr "含糖的早餐麥片與棉花糖。它會讓你回想起童年。" #: data/json/items/comestibles/junkfood.json msgid "corn cereal" msgid_plural "corn cereals" -msgstr[0] "" +msgstr[0] "早餐玉米" #. ~ Description for corn cereal #: data/json/items/comestibles/junkfood.json @@ -71011,7 +71251,7 @@ msgstr "用墨西哥玉米餅製成的鹽漬玉米片, 搭配奶酪、牛肉會 #: data/json/items/comestibles/junkfood.json msgid "cheese nachos" msgid_plural "cheese nachos" -msgstr[0] "" +msgstr[0] "奶酪辣味玉米片" #. ~ Description for {'str_sp': 'cheese nachos'} #: data/json/items/comestibles/junkfood.json @@ -71023,7 +71263,7 @@ msgstr "用墨西哥玉米餅製成的鹽漬玉米片, 搭配著奶酪。如果 #: data/json/items/comestibles/junkfood.json msgid "meat nachos" msgid_plural "meat nachos" -msgstr[0] "" +msgstr[0] "加肉辣味玉米片" #. ~ Conditional name for {'str_sp': 'meat nachos'} when FLAG matches #. CANNIBALISM @@ -71037,7 +71277,7 @@ msgstr[0] "加人肉玉米片" #: data/json/items/comestibles/junkfood.json msgid "nachos con chupacabra" msgid_plural "nachos con chupacabra" -msgstr[0] "" +msgstr[0] "加肉辣味玉米片(变异肉)" #. ~ Description for {'str_sp': 'meat nachos'} #: data/json/items/comestibles/junkfood.json @@ -71049,7 +71289,7 @@ msgstr "用墨西哥玉米餅製成的鹽漬玉米片, 搭配著肉。如果有 #: data/json/items/comestibles/junkfood.json msgid "meat nachos with cheese" msgid_plural "meat nachos with cheese" -msgstr[0] "" +msgstr[0] "加肉奶酪辣味玉米片" #. ~ Conditional name for {'str_sp': 'meat nachos with cheese'} when FLAG #. matches CANNIBALISM @@ -71063,7 +71303,7 @@ msgstr[0] "人肉起司玉米片" #: data/json/items/comestibles/junkfood.json msgid "cheese and chupacabra nachos" msgid_plural "cheese and chupacabra nachos" -msgstr[0] "" +msgstr[0] "加肉奶酪辣味玉米片(变异肉)" #. ~ Description for {'str_sp': 'meat nachos with cheese'} #: data/json/items/comestibles/junkfood.json @@ -71075,7 +71315,7 @@ msgstr "用墨西哥玉米餅製成的鹽漬玉米片, 搭配了奶酪與肉。 #: data/json/items/comestibles/junkfood.json msgid "pork stick" msgid_plural "pork sticks" -msgstr[0] "" +msgstr[0] "猪肉脯" #. ~ Description for pork stick #: data/json/items/comestibles/junkfood.json @@ -71085,7 +71325,7 @@ msgstr "鹽漬的豬肉。好吃, 只是吃的時候口會渴。" #: data/json/items/comestibles/junkfood.json msgid "microwave burrito" msgid_plural "microwave burritos" -msgstr[0] "" +msgstr[0] "微波玉米卷饼" #. ~ Description for microwave burrito #: data/json/items/comestibles/junkfood.json @@ -71097,7 +71337,7 @@ msgstr "微波食品的一种——小分量的牛排、奶酪与玉米煎饼装 #: data/json/items/comestibles/junkfood.json msgid "uncooked TV dinner" msgid_plural "uncooked TV dinners" -msgstr[0] "" +msgstr[0] "生速冻快餐" #. ~ Description for uncooked TV dinner #: data/json/items/comestibles/junkfood.json @@ -71109,7 +71349,7 @@ msgstr "加入了一磅的肉與一磅的碳水化合物! 若加熱後將是開 #: data/json/items/comestibles/junkfood.json msgid "cooked TV dinner" msgid_plural "cooked TV dinners" -msgstr[0] "" +msgstr[0] "熟速冻快餐" #. ~ Description for cooked TV dinner #: data/json/items/comestibles/junkfood.json @@ -71121,7 +71361,7 @@ msgstr "加入了一磅的肉與一磅的碳水化合物! 熱騰騰的溫度剛 #: data/json/items/comestibles/junkfood.json msgid "deep-fried chicken" msgid_plural "deep-fried chickens" -msgstr[0] "" +msgstr[0] "炸鸡" #. ~ Description for deep-fried chicken #: data/json/items/comestibles/junkfood.json @@ -71153,7 +71393,7 @@ msgstr "一份经过深加工的香肠,裹在面糊里炸熟的生热狗,可 #: data/json/items/comestibles/junkfood.json msgid "cooked corn dog" msgid_plural "cooked corn dogs" -msgstr[0] "" +msgstr[0] "熟玉米热狗" #. ~ Description for cooked corn dog #: data/json/items/comestibles/junkfood.json @@ -71165,7 +71405,7 @@ msgstr "一份经过深加工的香肠,裹在面糊里炸熟的热狗,比起 #: data/json/items/comestibles/junkfood.json msgid "homemade corn dog" msgid_plural "homemade corn dogs" -msgstr[0] "" +msgstr[0] "自制玉米热狗" #. ~ Description for homemade corn dog #: data/json/items/comestibles/junkfood.json @@ -71189,7 +71429,7 @@ msgstr "剛出爐的既蓬鬆可口並且淋上純正楓糖漿的美味巧克力 #: data/json/items/comestibles/junkfood.json msgid "chocolate waffle" msgid_plural "chocolate waffles" -msgstr[0] "" +msgstr[0] "巧克力华夫饼" #. ~ Description for chocolate waffle #: data/json/items/comestibles/junkfood.json @@ -71201,7 +71441,7 @@ msgstr "剛出爐的既蓬鬆可口並且淋上純正楓糖漿的美味巧克力 #: data/json/items/comestibles/junkfood.json msgid "cheese spread" msgid_plural "cheese spreads" -msgstr[0] "" +msgstr[0] "软干酪" #. ~ Description for cheese spread #: data/json/items/comestibles/junkfood.json @@ -71221,7 +71461,7 @@ msgstr "油炸馬鈴薯。有著美味的起士淋在上面。" #: data/json/items/comestibles/junkfood.json msgid "onion ring" msgid_plural "onion rings" -msgstr[0] "" +msgstr[0] "洋葱圈" #. ~ Description for onion ring #: data/json/items/comestibles/junkfood.json @@ -71231,7 +71471,7 @@ msgstr "反復油炸的洋蔥圈。香脆可口。" #: data/json/items/comestibles/junkfood.json msgid "uncooked hot dog" msgid_plural "uncooked hot dogs" -msgstr[0] "" +msgstr[0] "生热狗" #. ~ Description for {'str': 'uncooked hot dog'} #: data/json/items/comestibles/junkfood.json @@ -71243,7 +71483,7 @@ msgstr "一根经过大量加工的香肠,大灾变之前棒球比赛看台上 #: data/json/items/comestibles/junkfood.json msgid "campfire hot dog" msgid_plural "campfire hot dogs" -msgstr[0] "" +msgstr[0] "篝火热狗" #. ~ Description for {'str': 'campfire hot dog'} #: data/json/items/comestibles/junkfood.json @@ -71255,7 +71495,7 @@ msgstr "一根簡單的熱狗腸, 以明火煮熟。要是配上麵包就更完 #: data/json/items/comestibles/junkfood.json msgid "cooked hot dog" msgid_plural "cooked hot dogs" -msgstr[0] "" +msgstr[0] "熟热狗" #. ~ Description for {'str': 'cooked hot dog'} #: data/json/items/comestibles/junkfood.json @@ -71267,7 +71507,7 @@ msgstr "令人驚訝的是, 這並不是用狗肉做的。加熱過讓這熱狗 #: data/json/items/comestibles/junkfood.json msgid "malted milk ball" msgid_plural "malted milk balls" -msgstr[0] "" +msgstr[0] "麦丽酥" #. ~ Description for malted milk ball #: data/json/items/comestibles/junkfood.json @@ -71279,13 +71519,13 @@ msgstr "一份表面被巧克力包裹的松脆糖果。其中所含的麦芽给 #: data/json/items/comestibles/meat_dishes.json msgid "raw sausage" msgid_plural "raw sausages" -msgstr[0] "" +msgstr[0] "生香肠" #. ~ Conditional name for raw sausage when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "raw Mannwurst" msgid_plural "raw Mannwursts" -msgstr[0] "" +msgstr[0] "生人肉香肠" #. ~ Conditional name for raw sausage when COMPONENT_ID matches mutant #. ~ Conditional name for smoked sausage when COMPONENT_ID matches mutant @@ -71296,7 +71536,7 @@ msgstr[0] "" #, c-format msgid "sinister %s" msgid_plural "sinister %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for raw sausage #: data/json/items/comestibles/meat_dishes.json @@ -71306,13 +71546,13 @@ msgstr "一條沉重的生香腸, 已準備好用於煙燻或烹煮。" #: data/json/items/comestibles/meat_dishes.json msgid "smoked sausage" msgid_plural "smoked sausages" -msgstr[0] "" +msgstr[0] "熏香肠" #. ~ Conditional name for smoked sausage when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "smoked Mannwurst" msgid_plural "smoked Mannwursts" -msgstr[0] "" +msgstr[0] "熏人肉香肠" #. ~ Description for smoked sausage #: data/json/items/comestibles/meat_dishes.json @@ -71322,13 +71562,13 @@ msgstr "一條又大又重的香腸, 已經過醃製和煙燻, 可長期保存 #: data/json/items/comestibles/meat_dishes.json msgid "cooked sausage" msgid_plural "cooked sausages" -msgstr[0] "" +msgstr[0] "熟香肠" #. ~ Conditional name for cooked sausage when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "cooked Mannwurst" msgid_plural "cooked Mannwursts" -msgstr[0] "" +msgstr[0] "熟人肉香肠" #. ~ Description for cooked sausage #: data/json/items/comestibles/meat_dishes.json @@ -71375,13 +71615,13 @@ msgstr "香甜可口的香腸。最好趁新鮮時享用。" #: data/json/items/comestibles/meat_dishes.json msgid "bratwurst" msgid_plural "bratwursts" -msgstr[0] "" +msgstr[0] "德式香肠" #. ~ Conditional name for {'str': 'bratwurst'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "Mannbrat" msgid_plural "Mannbrats" -msgstr[0] "" +msgstr[0] "德式人肉肠" #. ~ Conditional name for {'str': 'bratwurst'} when COMPONENT_ID matches #. mutant @@ -71389,7 +71629,7 @@ msgstr[0] "" #, c-format msgid "baleful %s" msgid_plural "baleful %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str': 'bratwurst'} #: data/json/items/comestibles/meat_dishes.json @@ -71401,7 +71641,7 @@ msgstr "一種德國香腸,由切碎的肉製成,可用煎製或烤製。在 #: data/json/items/comestibles/meat_dishes.json msgid "royal beef" msgid_plural "royal beef" -msgstr[0] "" +msgstr[0] "蜂皇肉排" #. ~ Description for {'str_sp': 'royal beef'} #: data/json/items/comestibles/meat_dishes.json @@ -71425,7 +71665,7 @@ msgstr "一塊厚切鹹培根。供貨穩定, 熟食並即可食用, 加熱後 #: data/json/items/comestibles/meat_dishes.json msgid "smoked wasteland sausage" msgid_plural "smoked wasteland sausages" -msgstr[0] "" +msgstr[0] "烟熏废土香肠" #. ~ Conditional name for smoked wasteland sausage when COMPONENT_ID matches #. mutant @@ -71447,7 +71687,7 @@ msgstr "精瘦的香腸, 用天然腸衣與大量鹽漬的內臟所製成。勤 #: data/json/items/comestibles/meat_dishes.json msgid "raw wasteland sausage" msgid_plural "raw wasteland sausages" -msgstr[0] "" +msgstr[0] "生废土香肠" #. ~ Description for raw wasteland sausage #: data/json/items/comestibles/meat_dishes.json @@ -71458,7 +71698,7 @@ msgstr "精瘦的生香腸, 用天然腸衣與大量鹽漬的內臟所製成。 #: data/json/items/comestibles/meat_dishes.json msgid "cooked wasteland sausage" msgid_plural "cooked wasteland sausages" -msgstr[0] "" +msgstr[0] "熟废土香肠" #. ~ Description for cooked wasteland sausage #: data/json/items/comestibles/meat_dishes.json @@ -71480,7 +71720,7 @@ msgstr "也稱為炸豬皮, 這些油渣是將些許可食用的脂肪和皮, #: data/json/items/comestibles/meat_dishes.json msgid "glazed tenderloins" msgid_plural "glazed tenderloins" -msgstr[0] "" +msgstr[0] "蜜汁里脊" #. ~ Conditional name for {'str_sp': 'glazed tenderloins'} when COMPONENT_ID #. matches mutant @@ -71488,7 +71728,7 @@ msgstr[0] "" #, c-format msgid "grisly %s" msgid_plural "grisly %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str_sp': 'glazed tenderloins'} #: data/json/items/comestibles/meat_dishes.json @@ -71501,21 +71741,21 @@ msgstr "一塊具有完美調味及美味配菜的軟嫩肉排。一道既健康 #: data/json/items/comestibles/meat_dishes.json msgid "currywurst" msgid_plural "currywursts" -msgstr[0] "" +msgstr[0] "咖喱香肠" #. ~ Conditional name for currywurst when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "cheapskate %s" msgid_plural "cheapskate %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Conditional name for currywurst when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "bloodcurdling %s" msgid_plural "bloodcurdling %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for currywurst #: data/json/items/comestibles/meat_dishes.json @@ -71527,21 +71767,21 @@ msgstr "香腸澆上咖哩番茄沾醬。驚奇美味一起來!" #: data/json/items/comestibles/meat_dishes.json msgid "aspic" msgid_plural "aspics" -msgstr[0] "" +msgstr[0] "肉冻" #. ~ Conditional name for {'str': 'aspic'} when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "abomination %s" msgid_plural "abomination %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Conditional name for {'str': 'aspic'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "amoral %s" msgid_plural "amoral %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Description for {'str': 'aspic'} #: data/json/items/comestibles/meat_dishes.json @@ -71610,14 +71850,14 @@ msgstr "一份美味的金黃色香脆炸魚。" #: data/json/items/comestibles/meat_dishes.json msgid "lunch meat" msgid_plural "lunch meats" -msgstr[0] "" +msgstr[0] "午餐肉" #. ~ Conditional name for lunch meat when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "loathsome %s" msgid_plural "loathsome %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for lunch meat #: data/json/items/comestibles/meat_dishes.json @@ -71629,14 +71869,14 @@ msgstr "煮熟且醃製過的肉品,切成了薄片方便夾進三明治裡。 #: data/json/items/comestibles/meat_dishes.json msgid "bologna" msgid_plural "bologna" -msgstr[0] "" +msgstr[0] "博洛尼亚红肠" #. ~ Conditional name for {'str_sp': 'bologna'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "brat %s" msgid_plural "brat %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Conditional name for {'str_sp': 'bologna'} when COMPONENT_ID matches #. mutant @@ -71644,7 +71884,7 @@ msgstr[0] "" #, c-format msgid "bleak %s" msgid_plural "bleak %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str_sp': 'bologna'} #: data/json/items/comestibles/meat_dishes.json @@ -71657,7 +71897,7 @@ msgstr "正式名稱是波隆那香腸,這是以精細豬肉餡製成的醃製 #: data/json/items/comestibles/meat_dishes.json msgid "lutefisk" msgid_plural "lutefisks" -msgstr[0] "" +msgstr[0] "碱渍鱼" #. ~ Description for lutefisk #: data/json/items/comestibles/meat_dishes.json @@ -71670,7 +71910,7 @@ msgstr "鹼漬魚是一種利用鹼液來醃漬魚肉的保存方式。即使有 #: data/json/items/comestibles/meat_dishes.json msgid "SPAM" msgid_plural "SPAM" -msgstr[0] "" +msgstr[0] "午餐肉罐头" #. ~ Description for {'str_sp': 'SPAM'} #: data/json/items/comestibles/meat_dishes.json @@ -71683,7 +71923,7 @@ msgstr "罐頭豬肉產品, 有著不自然的粉紅色與奇怪的橡膠感, #: data/json/items/comestibles/meat_dishes.json msgid "holy SPAM of debugging" msgid_plural "holy SPAMs of debugging" -msgstr[0] "" +msgstr[0] "调试用午餐肉" #. ~ Description for {'str': 'holy SPAM of debugging', 'str_pl': 'holy SPAMs #. of debugging'} @@ -71696,7 +71936,7 @@ msgstr "一块神秘的午餐肉,包含了你一天里需要的所有卡路里 #: data/json/items/comestibles/meat_dishes.json msgid "canned sardine" msgid_plural "canned sardines" -msgstr[0] "" +msgstr[0] "罐装沙丁鱼" #. ~ Description for canned sardine #: data/json/items/comestibles/meat_dishes.json @@ -71721,7 +71961,7 @@ msgstr[0] "人肉香腸濃湯" #, c-format msgid "ghastly %s" msgid_plural "ghastly %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str': 'sausage gravy', 'str_pl': 'sausage gravies'} #: data/json/items/comestibles/meat_dishes.json @@ -71733,14 +71973,14 @@ msgstr "比司吉麵包、肉、美味的蘑菇湯加在一起成為一個奇妙 #: data/json/items/comestibles/meat_dishes.json msgid "pemmican" msgid_plural "pemmican" -msgstr[0] "" +msgstr[0] "干肉饼" #. ~ Conditional name for {'str_sp': 'pemmican'} when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "prepper %s" msgid_plural "prepper %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Conditional name for {'str_sp': 'pemmican'} when COMPONENT_ID matches #. mutant @@ -71748,7 +71988,7 @@ msgstr[0] "" #, c-format msgid "pernicious %s" msgid_plural "pernicious %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str_sp': 'pemmican'} #: data/json/items/comestibles/meat_dishes.json @@ -71761,20 +72001,20 @@ msgstr "將脂肪和蛋白質混合制作的一種營養豐富的高熱量食物 #: data/json/items/comestibles/meat_dishes.json msgid "hamburger helper" msgid_plural "hamburger helpers" -msgstr[0] "" +msgstr[0] "汉堡助手" #. ~ Conditional name for hamburger helper when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "hobo helper" msgid_plural "hobo helpers" -msgstr[0] "" +msgstr[0] "汉堡\"助手\"" #. ~ Conditional name for hamburger helper when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "heinous %s" msgid_plural "heinous %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for hamburger helper #: data/json/items/comestibles/meat_dishes.json @@ -71786,7 +72026,7 @@ msgstr "雖然叫漢堡幫手, 但只是一些麵條與起司淋上絞肉。有 #: data/json/items/comestibles/meat_dishes.json msgid "ravioli" msgid_plural "raviolis" -msgstr[0] "" +msgstr[0] "意式方饺" #. ~ Description for ravioli #: data/json/items/comestibles/meat_dishes.json @@ -71803,14 +72043,14 @@ msgstr[0] "辣醬湯" #: data/json/items/comestibles/meat_dishes.json msgid "chili con cabron" msgid_plural "chilis con cabron" -msgstr[0] "" +msgstr[0] "墨西哥辣人酱" #. ~ Conditional name for {'str': 'chili con carne', 'str_pl': 'chilis con #. carne'} when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json msgid "chili con chupacabra" msgid_plural "chilis con chupacabra" -msgstr[0] "" +msgstr[0] "墨西哥辣肉酱(变异肉)" #. ~ Description for {'str': 'chili con carne', 'str_pl': 'chilis con carne'} #: data/json/items/comestibles/meat_dishes.json @@ -71842,7 +72082,7 @@ msgstr "裡面海豚肉的含量少於 95% 了!" #: data/json/items/comestibles/meat_dishes.json msgid "canned salmon" msgid_plural "canned salmon" -msgstr[0] "" +msgstr[0] "罐装三文鱼" #. ~ Description for {'str_sp': 'canned salmon'} #: data/json/items/comestibles/meat_dishes.json @@ -71852,7 +72092,7 @@ msgstr "裝著亮粉紅色魚肉醬的罐頭!" #: data/json/items/comestibles/meat_dishes.json msgid "canned chicken" msgid_plural "canned chickens" -msgstr[0] "" +msgstr[0] "罐装鸡肉" #. ~ Description for canned chicken #: data/json/items/comestibles/meat_dishes.json @@ -71862,7 +72102,7 @@ msgstr "油亮的白醬雞肉。" #: data/json/items/comestibles/meat_dishes.json msgid "pickled herring" msgid_plural "pickled herring" -msgstr[0] "" +msgstr[0] "腌鲱鱼罐头" #. ~ Description for {'str_sp': 'pickled herring'} #: data/json/items/comestibles/meat_dishes.json @@ -71872,7 +72112,7 @@ msgstr "魚肉片醃在某種濃郁的白醬中。" #: data/json/items/comestibles/meat_dishes.json msgid "canned clam" msgid_plural "canned clams" -msgstr[0] "" +msgstr[0] "罐装蛤蜊" #. ~ Description for {'str': 'canned clam'} #: data/json/items/comestibles/meat_dishes.json @@ -71882,19 +72122,19 @@ msgstr "切碎的蛤蜊浸潤在罐頭湯中。" #: data/json/items/comestibles/meat_dishes.json msgid "clam chowder" msgid_plural "clam chowders" -msgstr[0] "" +msgstr[0] "蛤蜊浓汤" #. ~ Conditional name for clam chowder when COMPONENT_ID matches meat #: data/json/items/comestibles/meat_dishes.json msgid "meat chowder" msgid_plural "meat chowders" -msgstr[0] "" +msgstr[0] "肉碎浓汤" #. ~ Conditional name for clam chowder when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json msgid "monster chowder" msgid_plural "monster chowders" -msgstr[0] "" +msgstr[0] "肉碎浓汤(变异肉)" #. ~ Description for clam chowder #: data/json/items/comestibles/meat_dishes.json @@ -71913,7 +72153,7 @@ msgstr[0] "焗豆" #: data/json/items/comestibles/meat_dishes.json msgid "ork and beans" msgid_plural "ork and beans" -msgstr[0] "" +msgstr[0] "黄豆炖肉(变异肉)" #. ~ Description for {'str_sp': 'baked beans'} #: data/json/items/comestibles/meat_dishes.json @@ -71930,7 +72170,7 @@ msgstr[0] "肉絲炒飯" #: data/json/items/comestibles/meat_dishes.json msgid "mutant fried rice" msgid_plural "mutant fried rice" -msgstr[0] "" +msgstr[0] "肉块炒饭(变异肉)" #. ~ Description for {'str_sp': 'meat fried rice'} #: data/json/items/comestibles/meat_dishes.json @@ -71947,7 +72187,7 @@ msgstr[0] "豪華豆拌飯" #: data/json/items/comestibles/meat_dishes.json msgid "\"deluxe\" beans and rice" msgid_plural "\"deluxe\" beans and rice" -msgstr[0] "" +msgstr[0] "美味豆拌饭(变异肉)" #. ~ Description for {'str_sp': 'deluxe beans and rice'} #: data/json/items/comestibles/meat_dishes.json @@ -71959,20 +72199,20 @@ msgstr "一份加上肉絲和調味料的豆拌飯。好吃又有飽足感。" #: data/json/items/comestibles/meat_dishes.json msgid "meat pie" msgid_plural "meat pies" -msgstr[0] "" +msgstr[0] "肉派" #. ~ Conditional name for meat pie when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "prick pie" msgid_plural "prick pies" -msgstr[0] "" +msgstr[0] "肉派(人肉)" #. ~ Conditional name for meat pie when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "malignant %s" msgid_plural "malignant %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for meat pie #: data/json/items/comestibles/meat_dishes.json @@ -71982,20 +72222,20 @@ msgstr "一種有美味肉餡的烤餡餅。" #: data/json/items/comestibles/meat_dishes.json msgid "meat pizza" msgid_plural "meat pizzas" -msgstr[0] "" +msgstr[0] "肉香披萨" #. ~ Conditional name for meat pizza when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "poser pizza" msgid_plural "poser pizzas" -msgstr[0] "" +msgstr[0] "肉香披萨(人肉)" #. ~ Conditional name for meat pizza when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "miserable %s" msgid_plural "miserable %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for meat pizza #: data/json/items/comestibles/meat_dishes.json @@ -72007,7 +72247,7 @@ msgstr "一份加肉披萨,肉食者们的最爱,加入了大量切碎的肉 #: data/json/items/comestibles/meat_dishes.json msgid "supreme pizza" msgid_plural "supreme pizzas" -msgstr[0] "" +msgstr[0] "至尊披萨" #. ~ Description for supreme pizza #: data/json/items/comestibles/meat_dishes.json @@ -72024,7 +72264,7 @@ msgstr[0] "豪華炒蛋" #: data/json/items/comestibles/meat_dishes.json msgid "\"deluxe\" scrambled eggs" msgid_plural "\"deluxe\" scrambled eggs" -msgstr[0] "" +msgstr[0] "美味炒蛋(变异肉)" #. ~ Description for {'str_sp': 'deluxe scrambled eggs'} #: data/json/items/comestibles/meat_dishes.json @@ -72036,7 +72276,7 @@ msgstr "蓬鬆可口的炒蛋添加了其他的美味食材, 更加美味。" #: data/json/items/comestibles/meat_dishes.json msgid "canned meat" msgid_plural "canned meats" -msgstr[0] "" +msgstr[0] "罐装肉" #. ~ Conditional name for canned meat when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json @@ -72054,13 +72294,13 @@ msgstr "低鹽保存的肉。已經用水煮熟並製成罐頭, 保留了大部 #: data/json/items/comestibles/meat_dishes.json msgid "salted meat slice" msgid_plural "salted meat slices" -msgstr[0] "" +msgstr[0] "腌肉片" #. ~ Conditional name for salted meat slice when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "salted simpleton slice" msgid_plural "salted simpleton slices" -msgstr[0] "" +msgstr[0] "腌肉片(人肉)" #. ~ Description for salted meat slice #: data/json/items/comestibles/meat_dishes.json @@ -72077,7 +72317,7 @@ msgstr[0] "肉醬義大利麵" #: data/json/items/comestibles/meat_dishes.json msgid "scoundrel spaghetti" msgid_plural "scoundrel spaghettis" -msgstr[0] "" +msgstr[0] "恶棍意面" #. ~ Conditional name for {'str_sp': 'spaghetti bolognese'} when COMPONENT_ID #. matches mutant @@ -72085,7 +72325,7 @@ msgstr[0] "" #, c-format msgid "gnarly %s" msgid_plural "gnarly %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str_sp': 'spaghetti bolognese'} #: data/json/items/comestibles/meat_dishes.json @@ -72095,21 +72335,21 @@ msgstr "被厚重肉汁緊緊包裹的義大利麵, 太美味啦!" #: data/json/items/comestibles/meat_dishes.json msgid "lasagne" msgid_plural "lasagnes" -msgstr[0] "" +msgstr[0] "千层面" #. ~ Conditional name for lasagne when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "Luigi %s" msgid_plural "Luigi %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Conditional name for lasagne when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "monster %s" msgid_plural "monster %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for lasagne #: data/json/items/comestibles/meat_dishes.json @@ -72121,7 +72361,7 @@ msgstr "傳統義大利麵, 將千層麵層層交疊, 再佐以奶酪、醬汁 #: data/json/items/comestibles/meat_dishes.json msgid "fried SPAM" msgid_plural "fried SPAM" -msgstr[0] "" +msgstr[0] "煎午餐肉" #. ~ Description for {'str_sp': 'fried SPAM'} #: data/json/items/comestibles/meat_dishes.json @@ -72131,21 +72371,21 @@ msgstr "煎過的午餐肉, 其實還挺美味的。" #: data/json/items/comestibles/meat_dishes.json msgid "cheeseburger" msgid_plural "cheeseburgers" -msgstr[0] "" +msgstr[0] "奶酪汉堡包" #. ~ Conditional name for cheeseburger when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "chump %s" msgid_plural "chump %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Conditional name for cheeseburger when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "chilling %s" msgid_plural "chilling %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for cheeseburger #: data/json/items/comestibles/meat_dishes.json @@ -72157,20 +72397,20 @@ msgstr "这个三明治里塞满了美味的碎肉、奶酪和调料。灾前烹 #: data/json/items/comestibles/meat_dishes.json msgid "hamburger" msgid_plural "hamburgers" -msgstr[0] "" +msgstr[0] "汉堡包" #. ~ Conditional name for hamburger when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "bobburger" msgid_plural "bobburgers" -msgstr[0] "" +msgstr[0] "\"汉\"堡包" #. ~ Conditional name for hamburger when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "horrible %s" msgid_plural "horrible %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for hamburger #: data/json/items/comestibles/meat_dishes.json @@ -72180,7 +72420,7 @@ msgstr "夾著一片漢堡肉以及調味料。" #: data/json/items/comestibles/meat_dishes.json msgid "sloppy joe" msgid_plural "sloppy joes" -msgstr[0] "" +msgstr[0] "调羹汉堡" #. ~ Conditional name for sloppy joe when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json @@ -72193,7 +72433,7 @@ msgstr[0] "三人治" #, c-format msgid "suspicious %s" msgid_plural "suspicious %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for sloppy joe #: data/json/items/comestibles/meat_dishes.json @@ -72205,21 +72445,21 @@ msgstr "一個漢堡, 加入了絞肉以及番茄沙司。" #: data/json/items/comestibles/meat_dishes.json msgid "taco" msgid_plural "tacos" -msgstr[0] "" +msgstr[0] "墨西哥卷饼" #. ~ Conditional name for taco when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "tio %s" msgid_plural "tio %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Conditional name for taco when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "terrifying %s" msgid_plural "terrifying %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for taco #: data/json/items/comestibles/meat_dishes.json @@ -72231,13 +72471,13 @@ msgstr "一種傳統的墨西哥食物, 用墨西哥玉米餅折疊或捲起肉 #: data/json/items/comestibles/meat_dishes.json msgid "pickled meat" msgid_plural "pickled meats" -msgstr[0] "" +msgstr[0] "腌肉" #. ~ Conditional name for pickled meat when FLAG matches CANNIBALISM #: data/json/items/comestibles/meat_dishes.json msgid "pickled punk" msgid_plural "pickled punks" -msgstr[0] "" +msgstr[0] "腌人肉" #. ~ Description for pickled meat #: data/json/items/comestibles/meat_dishes.json @@ -72248,7 +72488,7 @@ msgstr "這是一份醃過的肉罐頭。美味又營養。" #: data/json/items/comestibles/meat_dishes.json msgid "dehydrated meat" msgid_plural "dehydrated meats" -msgstr[0] "" +msgstr[0] "脱水肉块" #. ~ Conditional name for dehydrated meat when FLAG matches CANNIBALISM #. ~ Conditional name for rehydrated meat when FLAG matches CANNIBALISM @@ -72256,7 +72496,7 @@ msgstr[0] "" #, c-format msgid "%s, human" msgid_plural "%s, human" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Description for dehydrated meat #: data/json/items/comestibles/meat_dishes.json @@ -72268,7 +72508,7 @@ msgstr "脫水過的肉片。在合適的儲存下, 這個乾燥食物能夠保 #: data/json/items/comestibles/meat_dishes.json msgid "rehydrated meat" msgid_plural "rehydrated meats" -msgstr[0] "" +msgstr[0] "水发肉块" #. ~ Description for rehydrated meat #: data/json/items/comestibles/meat_dishes.json @@ -72280,7 +72520,7 @@ msgstr "沖調過的脫水肉乾, 重新加了水之後讓這東西變得更好 #: data/json/items/comestibles/meat_dishes.json msgid "haggis" msgid_plural "haggises" -msgstr[0] "" +msgstr[0] "肉馅羊肚" #. ~ Conditional name for {'str': 'haggis', 'str_pl': 'haggises'} when FLAG #. matches CANNIBALISM @@ -72290,7 +72530,7 @@ msgstr[0] "" #, c-format msgid "human %s" msgid_plural "human %s" -msgstr[0] "" +msgstr[0] "%s(人肉)" #. ~ Description for {'str': 'haggis', 'str_pl': 'haggises'} #: data/json/items/comestibles/meat_dishes.json @@ -72326,7 +72566,7 @@ msgstr[0] "生肉手卷" #, c-format msgid "troubling %s" msgid_plural "troubling %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str_sp': 'meat temaki'} #: data/json/items/comestibles/meat_dishes.json @@ -72348,7 +72588,7 @@ msgstr "美味的薄片生魚肉與一些可口的蔬菜。" #: data/json/items/comestibles/meat_dishes.json msgid "dehydrated tainted meat" msgid_plural "dehydrated tainted meats" -msgstr[0] "" +msgstr[0] "脱水感染肉块" #. ~ Description for dehydrated tainted meat #: data/json/items/comestibles/meat_dishes.json @@ -72360,14 +72600,14 @@ msgstr "一些受污染的肉, 為了讓它不腐敗已作好乾燥處理。如 #: data/json/items/comestibles/meat_dishes.json msgid "pelmeni" msgid_plural "pelmenis" -msgstr[0] "" +msgstr[0] "俄式饺子" #. ~ Conditional name for pelmeni when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json #, c-format msgid "perilous %s" msgid_plural "perilous %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for pelmeni #: data/json/items/comestibles/meat_dishes.json @@ -72379,13 +72619,13 @@ msgstr "用薄麵皮將肉類內餡包起, 煮熟後就是份美味的餃子。" #: data/json/items/comestibles/meat_dishes.json msgid "homemade burrito" msgid_plural "homemade burritos" -msgstr[0] "" +msgstr[0] "自制玉米卷饼" #. ~ Conditional name for homemade burrito when COMPONENT_ID matches mutant #: data/json/items/comestibles/meat_dishes.json msgid "bone-chilling burrito" msgid_plural "bone-chilling burritos" -msgstr[0] "" +msgstr[0] "自制玉米卷饼(变异肉)" #. ~ Description for homemade burrito #: data/json/items/comestibles/meat_dishes.json @@ -72411,7 +72651,7 @@ msgstr "一個完整的醫療包, 包含繃帶、局部麻醉劑跟快速癒合 #: data/json/items/comestibles/med.json msgid "melatonin tablet" msgid_plural "melatonin tablets" -msgstr[0] "" +msgstr[0] "褪黑素片" #. ~ Use action activation_message for melatonin tablet. #: data/json/items/comestibles/med.json @@ -72474,7 +72714,7 @@ msgstr "一種強效的抗菌藥物,用於預防或阻止感染擴散。這是 #: data/json/items/comestibles/med.json msgid "antifungal drug" msgid_plural "antifungal drugs" -msgstr[0] "" +msgstr[0] "抗真菌药" #. ~ Description for {'str': 'antifungal drug'} #: data/json/items/comestibles/med.json @@ -72486,7 +72726,7 @@ msgstr "能夠有效對抗真菌感染的化學藥品, 適用於生物。" #: data/json/items/comestibles/med.json msgid "antiparasitic drug" msgid_plural "antiparasitic drug" -msgstr[0] "" +msgstr[0] "抗寄生药" #. ~ Description for {'str_sp': 'antiparasitic drug'} #: data/json/items/comestibles/med.json @@ -72499,7 +72739,7 @@ msgstr "用在消除寄生蟲侵擾的泛用化學藥片。雖然是用於寵物 #: data/json/items/comestibles/med.json msgid "aspirin" msgid_plural "aspirins" -msgstr[0] "" +msgstr[0] "阿司匹林" #. ~ Use action activation_message for {'str': 'aspirin'}. #: data/json/items/comestibles/med.json @@ -72516,7 +72756,7 @@ msgstr "溫和抗發炎的乙酰水楊酸。服用後可緩解疼痛和腫脹。 #: data/json/items/comestibles/med.json msgid "bandage" msgid_plural "bandages" -msgstr[0] "" +msgstr[0] "绷带" #. ~ Description for {'str': 'bandage'} #: data/json/items/comestibles/med.json @@ -72526,7 +72766,7 @@ msgstr "簡單的棉布繃帶。用來治療少量的傷害。" #: data/json/items/comestibles/med.json msgid "makeshift bandage" msgid_plural "makeshift bandages" -msgstr[0] "" +msgstr[0] "简易绷带" #. ~ Description for makeshift bandage #: data/json/items/comestibles/med.json @@ -72536,7 +72776,7 @@ msgstr "簡單的布製繃帶。聊勝於無。" #: data/json/items/comestibles/med.json msgid "bleached makeshift bandage" msgid_plural "bleached makeshift bandages" -msgstr[0] "" +msgstr[0] "简易绷带(漂白)" #. ~ Description for {'str': 'bleached makeshift bandage'} #: data/json/items/comestibles/med.json @@ -72546,7 +72786,7 @@ msgstr "簡單的布製繃帶。它看起來很白, 就像真正的繃帶一樣 #: data/json/items/comestibles/med.json msgid "boiled makeshift bandage" msgid_plural "boiled makeshift bandages" -msgstr[0] "" +msgstr[0] "简易绷带(煮沸)" #. ~ Description for {'str': 'boiled makeshift bandage'} #: data/json/items/comestibles/med.json @@ -72569,7 +72809,7 @@ msgstr "粉狀的化學殺菌劑,這種碘化鉍鉀粉末可以快速輕鬆的 #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json msgid "caffeinated chewing gum" msgid_plural "caffeinated chewing gum" -msgstr[0] "" +msgstr[0] "咖啡因口香糖" #. ~ Description for {'str_sp': 'caffeinated chewing gum'} #: data/json/items/comestibles/med.json @@ -72579,7 +72819,7 @@ msgstr "添加了咖啡因的口香糖,不含糖,能够提神醒脑。" #: data/json/items/comestibles/med.json msgid "caffeine pill" msgid_plural "caffeine pills" -msgstr[0] "" +msgstr[0] "咖啡因含片" #. ~ Use action activation_message for caffeine pill. #: data/json/items/comestibles/med.json @@ -72596,7 +72836,7 @@ msgstr "無牌的咖啡錠, 效果強大。想要通宵達旦工作的利器, #: data/json/items/comestibles/med.json msgid "chewing tobacco" msgid_plural "chewing tobaccos" -msgstr[0] "" +msgstr[0] "咀嚼烟草" #. ~ Description for chewing tobacco #: data/json/items/comestibles/med.json @@ -72639,7 +72879,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "chloroform soaked rag" msgid_plural "chloroform soaked rags" -msgstr[0] "" +msgstr[0] "氯仿布条" #. ~ Description for chloroform soaked rag #: data/json/items/comestibles/med.json @@ -72685,7 +72925,7 @@ msgstr "古柯葉能被提取成白色粉末結晶的毒品。其刺激的屬性 #: data/json/items/comestibles/med.json msgid "methacola" msgid_plural "methacolas" -msgstr[0] "" +msgstr[0] "冰毒可乐" #. ~ Description for methacola #: data/json/items/comestibles/med.json @@ -72754,7 +72994,7 @@ msgstr "適合白天服用的感冒藥, 治療感冒與流感。不嗜睡的配 #: data/json/items/comestibles/med.json msgid "antiseptic" msgid_plural "antiseptic" -msgstr[0] "" +msgstr[0] "抗菌剂" #. ~ Description for {'str_sp': 'antiseptic'} #: data/json/items/comestibles/med.json @@ -72764,7 +73004,7 @@ msgstr "常用於消毒感染傷口的強效消毒劑。" #: data/json/items/comestibles/med.json msgid "makeshift antiseptic" msgid_plural "makeshift antiseptics" -msgstr[0] "" +msgstr[0] "简易抗菌剂" #. ~ Description for makeshift antiseptic #: data/json/items/comestibles/med.json @@ -72787,7 +73027,7 @@ msgstr "強力的苯甲二氮䓬藥劑, 用於治療肌肉痙攣, 焦慮, 癲癇 #: data/json/items/comestibles/med.json msgid "high quality shatter" msgid_plural "high quality shatter" -msgstr[0] "" +msgstr[0] "高纯度大麻块" #. ~ Use action activation_message for {'str_sp': 'high quality shatter'}. #: data/json/items/comestibles/med.json @@ -72808,7 +73048,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "high quality wax" msgid_plural "high quality wax" -msgstr[0] "" +msgstr[0] "高纯度大麻蜡" #. ~ Use action activation_message for {'str_sp': 'high quality wax'}. #: data/json/items/comestibles/med.json @@ -72828,7 +73068,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "high quality crude oil" msgid_plural "high quality crude oil" -msgstr[0] "" +msgstr[0] "高纯度大麻油" #. ~ Use action activation_message for {'str_sp': 'high quality crude oil'}. #: data/json/items/comestibles/med.json @@ -72846,7 +73086,7 @@ msgstr "一份从大麻提取液中浓缩提纯而成的大麻油。它仍然残 #: data/json/items/comestibles/med.json msgid "low quality crude oil" msgid_plural "low quality crude oil" -msgstr[0] "" +msgstr[0] "低纯度大麻油" #. ~ Use action activation_message for {'str_sp': 'low quality crude oil'}. #. ~ Use action activation_message for {'str_sp': 'filtered low quality crude @@ -72868,7 +73108,7 @@ msgstr "一份从大麻提取液中浓缩提纯而成的低级大麻油。它仍 #: data/json/items/comestibles/med.json msgid "(ethanol) low quality crude oil" msgid_plural "(ethanol) low quality crude oil" -msgstr[0] "" +msgstr[0] "低纯度大麻油(乙醇)" #. ~ Description for {'str_sp': '(ethanol) low quality crude oil'} #: data/json/items/comestibles/med.json @@ -72881,7 +73121,7 @@ msgstr "一份从大麻提取液中浓缩提纯而成的低级大麻油。它已 #: data/json/items/comestibles/med.json msgid "(ethanol) high quality crude oil" msgid_plural "(ethanol) high quality crude oil" -msgstr[0] "" +msgstr[0] "高纯度大麻油(乙醇)" #. ~ Description for {'str_sp': '(ethanol) high quality crude oil'} #: data/json/items/comestibles/med.json @@ -72894,7 +73134,7 @@ msgstr "一份从大麻提取液中浓缩提纯而成的大麻油。它已经用 #: data/json/items/comestibles/med.json msgid "(ethanol) filtered low quality crude oil" msgid_plural "(ethanol) filtered low quality crude oil" -msgstr[0] "" +msgstr[0] "低纯度大麻油(已过滤)" #. ~ Description for {'str_sp': '(ethanol) filtered low quality crude oil'} #: data/json/items/comestibles/med.json @@ -72907,7 +73147,7 @@ msgstr "一份从大麻提取液中浓缩提纯而成的低级大麻油。它已 #: data/json/items/comestibles/med.json msgid "(ethanol) filtered high quality crude oil" msgid_plural "(ethanol) filtered high quality crude oil" -msgstr[0] "" +msgstr[0] "高纯度大麻油(已过滤)" #. ~ Description for {'str_sp': '(ethanol) filtered high quality crude oil'} #: data/json/items/comestibles/med.json @@ -72920,7 +73160,7 @@ msgstr "一份从大麻提取液中浓缩提纯而成的大麻油。它已经用 #: data/json/items/comestibles/med.json msgid "filtered low quality crude oil" msgid_plural "filtered low quality crude oil" -msgstr[0] "" +msgstr[0] "低纯度大麻油(已蒸馏)" #. ~ Description for {'str_sp': 'filtered low quality crude oil'} #: data/json/items/comestibles/med.json @@ -72935,7 +73175,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "filtered high quality crude oil" msgid_plural "filtered high quality crude oil" -msgstr[0] "" +msgstr[0] "高纯度大麻油(已蒸馏)" #. ~ Description for {'str_sp': 'filtered high quality crude oil'} #: data/json/items/comestibles/med.json @@ -72950,7 +73190,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "high quality distillate (heads)" msgid_plural "high quality distillate (heads)" -msgstr[0] "" +msgstr[0] "高纯度大麻馏分(头)" #. ~ Description for {'str_sp': 'high quality distillate (heads)'} #: data/json/items/comestibles/med.json @@ -72963,7 +73203,7 @@ msgstr "一份高度浓缩的大麻精油。这是从一批大麻油中精馏所 #: data/json/items/comestibles/med.json msgid "high quality distillate (tails)" msgid_plural "high quality distillate (tails)" -msgstr[0] "" +msgstr[0] "高纯度大麻馏分(尾)" #. ~ Description for {'str_sp': 'high quality distillate (tails)'} #: data/json/items/comestibles/med.json @@ -72976,7 +73216,7 @@ msgstr "一份高度浓缩的大麻精油。这是从一批大麻油中精馏所 #: data/json/items/comestibles/med.json msgid "high quality distillate" msgid_plural "high quality distillate" -msgstr[0] "" +msgstr[0] "高纯度大麻提取液" #. ~ Use action activation_message for {'str_sp': 'high quality distillate'}. #: data/json/items/comestibles/med.json @@ -72997,7 +73237,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "high quality distillate cartridge" msgid_plural "high quality distillate cartridges" -msgstr[0] "" +msgstr[0] "高纯度大麻精油液" #. ~ Use action activation_message for {'str': 'high quality distillate #. cartridge'}. @@ -73019,7 +73259,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "electronic cigarette" msgid_plural "electronic cigarettes" -msgstr[0] "" +msgstr[0] "电子香烟" #. ~ Description for electronic cigarette #: data/json/items/comestibles/med.json @@ -73032,7 +73272,7 @@ msgstr "這個電子裝置把尼古丁和調味劑液體蒸騰混合在一起。 #: data/json/items/comestibles/med.json msgid "saline eye drop" msgid_plural "saline eye drops" -msgstr[0] "" +msgstr[0] "生理盐水眼药水" #. ~ Description for {'str': 'saline eye drop'} #: data/json/items/comestibles/med.json @@ -73043,6 +73283,7 @@ msgstr "無菌生理食鹽眼藥水。可用於治療乾眼, 或洗出在眼裡 #: data/json/items/comestibles/med.json #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "chewing gum" msgid_plural "chewing gum" msgstr[0] "口香糖" @@ -73055,7 +73296,7 @@ msgstr "亮粉色的无糖口香糖。" #: data/json/items/comestibles/med.json msgid "hand-rolled cigarette" msgid_plural "hand-rolled cigarettes" -msgstr[0] "" +msgstr[0] "手卷烟" #. ~ Description for hand-rolled cigarette #: data/json/items/comestibles/med.json @@ -73087,7 +73328,7 @@ msgstr "由嗎啡萃取的高濃度鴉片類麻醉劑。極其容易上癮, 用 #: data/json/items/comestibles/med.json msgid "potassium iodide tablet" msgid_plural "potassium iodide tablets" -msgstr[0] "" +msgstr[0] "碘化钾片" #. ~ Use action activation_message for potassium iodide tablet. #: data/json/items/comestibles/med.json @@ -73111,7 +73352,7 @@ msgstr "大麻、狼藥、草。不管你怎麼叫他, 把它用張紙捲起來, #: data/json/items/comestibles/med.json msgid "pink tab" msgid_plural "pink tabs" -msgstr[0] "" +msgstr[0] "邮票毒品" #. ~ Use action activation_message for pink tab. #: data/json/items/comestibles/med.json @@ -73128,7 +73369,7 @@ msgstr "像郵票一樣的粉紅色小片,已經配有某種藥物。真的只 #: data/json/items/comestibles/med.json msgid "medical gauze" msgid_plural "medical gauzes" -msgstr[0] "" +msgstr[0] "医用纱布" #. ~ Description for medical gauze #: data/json/items/comestibles/med.json @@ -73159,7 +73400,7 @@ msgstr "一個高度成癮性的強力興奮劑。雖然能夠非常有效地提 #: data/json/items/comestibles/med.json msgid "morphine" msgid_plural "morphines" -msgstr[0] "" +msgstr[0] "吗啡" #. ~ Description for morphine #: data/json/items/comestibles/med.json @@ -73171,7 +73412,7 @@ msgstr "一種非常強力的半合成麻醉劑, 在醫院用於緩解強烈疼 #: data/json/items/comestibles/med.json msgid "mugwort oil" msgid_plural "mugwort oils" -msgstr[0] "" +msgstr[0] "艾蒿油" #. ~ Description for mugwort oil #: data/json/items/comestibles/med.json @@ -73183,7 +73424,7 @@ msgstr "由艾草作成的油, 攝取後或許能殺死寄生蟲。配水喝吧! #: data/json/items/comestibles/med.json msgid "nicotine gum" msgid_plural "nicotine gum" -msgstr[0] "" +msgstr[0] "尼古丁口香糖" #. ~ Description for {'str_sp': 'nicotine gum'} #: data/json/items/comestibles/med.json @@ -73207,7 +73448,7 @@ msgstr "適合夜晚服用的感冒藥, 治療感冒與流感。會造成嗜睡, #: data/json/items/comestibles/med.json msgid "oxycodone" msgid_plural "oxycodones" -msgstr[0] "" +msgstr[0] "羟考酮" #. ~ Use action activation_message for oxycodone. #: data/json/items/comestibles/med.json @@ -73224,7 +73465,7 @@ msgstr "強效半合成麻醉劑, 用於治療持續疼痛, 具有成癮性。" #: data/json/items/comestibles/med.json msgid "Ambien" msgid_plural "Ambien" -msgstr[0] "" +msgstr[0] "安眠药" #. ~ Description for {'str_sp': 'Ambien'} #: data/json/items/comestibles/med.json @@ -73236,7 +73477,7 @@ msgstr "會產生依賴性與多種身心副作用的鎮靜劑。用來治療失 #: data/json/items/comestibles/med.json msgid "poppy painkiller" msgid_plural "poppy painkillers" -msgstr[0] "" +msgstr[0] "罂粟止痛药" #. ~ Use action activation_message for poppy painkiller. #: data/json/items/comestibles/med.json @@ -73254,7 +73495,7 @@ msgstr "突變罌粟花所提煉產生的強效鴉片類藥物。這藥物不會 #: data/json/items/comestibles/med.json msgid "poppy sleep" msgid_plural "poppy sleeps" -msgstr[0] "" +msgstr[0] "罂粟安眠药" #. ~ Description for poppy sleep #: data/json/items/comestibles/med.json @@ -73276,7 +73517,7 @@ msgstr "以突變罌粟製成的止咳藥, 會令你昏昏欲睡。" #: data/json/items/comestibles/med.json msgid "Prozac" msgid_plural "Prozac" -msgstr[0] "" +msgstr[0] "百忧解" #. ~ Description for {'str_sp': 'Prozac'} #: data/json/items/comestibles/med.json @@ -73291,7 +73532,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "Prussian blue tablet" msgid_plural "Prussian blue tablets" -msgstr[0] "" +msgstr[0] "普鲁士蓝药片" #. ~ Use action activation_message for {'str': 'Prussian blue tablet'}. #: data/json/items/comestibles/med.json @@ -73320,7 +73561,7 @@ msgstr "粉末狀的抗出血化合物, 能與血液發生反應, 立即形成 #: data/json/items/comestibles/med.json msgid "saline solution" msgid_plural "saline solutions" -msgstr[0] "" +msgstr[0] "生理盐水" #. ~ Description for saline solution #: data/json/items/comestibles/med.json @@ -73332,7 +73573,7 @@ msgstr "消毒過的食鹽水, 常用於靜脈注射, 或是洗去眼睛裡的 #: data/json/items/comestibles/med.json msgid "Thorazine" msgid_plural "Thorazine" -msgstr[0] "" +msgstr[0] "冬眠灵" #. ~ Description for {'str_sp': 'Thorazine'} #: data/json/items/comestibles/med.json @@ -73345,7 +73586,7 @@ msgstr "治療精神病的藥物。用於穩定大腦化學物質, 它可以阻 #: data/json/items/comestibles/med.json msgid "thyme oil" msgid_plural "thyme oils" -msgstr[0] "" +msgstr[0] "百里香精油" #. ~ Description for thyme oil #: data/json/items/comestibles/med.json @@ -73357,7 +73598,7 @@ msgstr "从百里香中提取的精油,可以作为轻度刺激性的抗菌剂 #: data/json/items/comestibles/med.json msgid "rolling tobacco" msgid_plural "rolling tobaccos" -msgstr[0] "" +msgstr[0] "卷烟烟草" #. ~ Use action activation_message for rolling tobacco. #: data/json/items/comestibles/med.json @@ -73376,7 +73617,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "tramadol" msgid_plural "tramadols" -msgstr[0] "" +msgstr[0] "曲马朵" #. ~ Use action activation_message for tramadol. #: data/json/items/comestibles/med.json @@ -73393,7 +73634,7 @@ msgstr "一種能夠用於治療中度疼痛的止痛藥。效果會持續幾個 #: data/json/items/comestibles/med.json msgid "gamma globulin shot" msgid_plural "gamma globulin shots" -msgstr[0] "" +msgstr[0] "丙种球蛋白注射剂" #. ~ Description for gamma globulin shot #: data/json/items/comestibles/med.json @@ -73406,7 +73647,7 @@ msgstr "該免疫球蛋白注射器以靜脈注射濃縮的抗體以暫時增強 #: data/json/items/comestibles/med.json msgid "multivitamin" msgid_plural "multivitamins" -msgstr[0] "" +msgstr[0] "复合维生素" #. ~ Use action activation_message for multivitamin. #. ~ Use action activation_message for calcium tablet. @@ -73427,7 +73668,7 @@ msgstr "包裝成膠囊藥丸形式的必備膳食營養素。無法均衡飲食 #: data/json/items/comestibles/med.json msgid "calcium tablet" msgid_plural "calcium tablets" -msgstr[0] "" +msgstr[0] "钙片" #. ~ Description for calcium tablet #: data/json/items/comestibles/med.json @@ -73439,7 +73680,7 @@ msgstr "白色鈣片。在災變之前骨質疏鬆的老年人用它來補充鈣 #: data/json/items/comestibles/med.json msgid "bone meal tablet" msgid_plural "bone meal tablets" -msgstr[0] "" +msgstr[0] "骨粉片" #. ~ Description for bone meal tablet #: data/json/items/comestibles/med.json @@ -73451,7 +73692,7 @@ msgstr "由骨粉製成的自製鈣質補充劑。味道糟糕且難以下嚥, #: data/json/items/comestibles/med.json msgid "flavored bone meal tablet" msgid_plural "flavored bone meal tablets" -msgstr[0] "" +msgstr[0] "风味骨粉片" #. ~ Description for flavored bone meal tablet #: data/json/items/comestibles/med.json @@ -73464,7 +73705,7 @@ msgstr "一份用骨粉制成的自制钙补充剂。由于添加了甜味剂来 #: data/json/items/comestibles/med.json msgid "gummy vitamin" msgid_plural "gummy vitamins" -msgstr[0] "" +msgstr[0] "维他命树脂糖" #. ~ Description for gummy vitamin #: data/json/items/comestibles/med.json @@ -73477,7 +73718,7 @@ msgstr "包裝成軟糖形式的必備膳食營養素。無法均衡飲食時的 #: data/json/items/comestibles/med.json msgid "injectable vitamin B" msgid_plural "injectable vitamin Bs" -msgstr[0] "" +msgstr[0] "注射用维生素B" #. ~ Use action activation_message for injectable vitamin B. #: data/json/items/comestibles/med.json @@ -73494,7 +73735,7 @@ msgstr "裝有淡黃色液體的小瓶, 含有注射用的水溶性維他命 B #: data/json/items/comestibles/med.json msgid "injectable iron" msgid_plural "injectable irons" -msgstr[0] "" +msgstr[0] "注射用铁补充剂" #. ~ Use action activation_message for injectable iron. #: data/json/items/comestibles/med.json @@ -73537,7 +73778,7 @@ msgstr "" #: data/json/items/comestibles/med.json msgid "antiseptic soaked rag" msgid_plural "antiseptic soaked rags" -msgstr[0] "" +msgstr[0] "抗菌布条" #. ~ Description for {'str': 'antiseptic soaked rag'} #: data/json/items/comestibles/med.json @@ -73561,7 +73802,7 @@ msgstr "乾淨潔白的蓬鬆棉球。用消毒劑浸泡過,傷口消毒時十 #: data/json/items/comestibles/med.json msgid "weak antibiotics" msgid_plural "weak antibiotics" -msgstr[0] "" +msgstr[0] "弱效抗生素" #. ~ Description for {'str_sp': 'weak antibiotics'} #: data/json/items/comestibles/med.json @@ -73574,7 +73815,7 @@ msgstr "一種用來抑制感染的泛用型抗生素。藥效不足以清除感 #: data/json/items/comestibles/med.json msgid "heartburn medicine" msgid_plural "heartburn medicines" -msgstr[0] "" +msgstr[0] "胃药" #. ~ Use action activation_message for heartburn medicine. #: data/json/items/comestibles/med.json @@ -73627,7 +73868,7 @@ msgstr "從香蒲中收穫的透明膠質,具有防腐功能,可作為止痛 #: data/json/items/comestibles/med.json msgid "strong antibiotics" msgid_plural "strong antibiotics" -msgstr[0] "" +msgstr[0] "强效抗生素" #. ~ Description for {'str_sp': 'strong antibiotics'} #: data/json/items/comestibles/med.json @@ -73652,7 +73893,7 @@ msgstr "一般的軍用口糧包裝盒,你不應該看到這個。" #: data/json/items/comestibles/mre.json data/json/obsoletion/items.json msgid "MRE small box" msgid_plural "MRE small boxes" -msgstr[0] "" +msgstr[0] "MRE 小包装盒" #. ~ Description for {'str': 'MRE small box', 'str_pl': 'MRE small boxes'} #: data/json/items/comestibles/mre.json data/json/obsoletion/items.json @@ -73662,7 +73903,7 @@ msgstr "一般的軍用口糧小包裝盒,你不應該看到這個。" #: data/json/items/comestibles/mre.json msgid "MRE entree" msgid_plural "MRE entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜" #. ~ Description for {'str': 'MRE entree'} #: data/json/items/comestibles/mre.json @@ -74045,7 +74286,7 @@ msgstr "" #: data/json/items/comestibles/mre.json msgid "chili & beans entree" msgid_plural "chili & beans entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(辣椒炒豆)" #. ~ Description for chili & beans entree #: data/json/items/comestibles/mre.json @@ -74057,7 +74298,7 @@ msgstr "一份軍用口糧的辣豆醬主菜, 能夠保存到近乎永遠。經 #: data/json/items/comestibles/mre.json msgid "BBQ beef entree" msgid_plural "BBQ beef entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(烤牛肉)" #. ~ Description for {'str': 'BBQ beef entree'} #: data/json/items/comestibles/mre.json @@ -74069,7 +74310,7 @@ msgstr "一份軍用口糧的BBQ烤牛主菜, 能夠保存到近乎永遠。經 #: data/json/items/comestibles/mre.json msgid "chicken noodle entree" msgid_plural "chicken noodle entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(鸡肉面)" #. ~ Description for chicken noodle entree #: data/json/items/comestibles/mre.json @@ -74081,7 +74322,7 @@ msgstr "一份軍用口糧的雞肉麵主菜, 能夠保存到近乎永遠。經 #: data/json/items/comestibles/mre.json msgid "spaghetti entree" msgid_plural "spaghetti entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(意大利面)" #. ~ Description for spaghetti entree #: data/json/items/comestibles/mre.json @@ -74093,7 +74334,7 @@ msgstr "一份軍用口糧的義大利麵主菜, 能夠保存到近乎永遠。 #: data/json/items/comestibles/mre.json msgid "chicken chunks entree" msgid_plural "chicken chunks entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(炸鸡块)" #. ~ Description for chicken chunks entree #: data/json/items/comestibles/mre.json @@ -74105,7 +74346,7 @@ msgstr "一份軍用口糧的炸雞塊主菜, 能夠保存到近乎永遠。經 #: data/json/items/comestibles/mre.json msgid "beef taco entree" msgid_plural "beef taco entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(墨西哥牛肉卷)" #. ~ Description for {'str': 'beef taco entree'} #: data/json/items/comestibles/mre.json @@ -74117,7 +74358,7 @@ msgstr "一份軍用口糧的牛肉塔可餅主菜, 能夠保存到近乎永遠 #: data/json/items/comestibles/mre.json msgid "beef brisket entree" msgid_plural "beef brisket entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(炖牛腩)" #. ~ Description for {'str': 'beef brisket entree'} #: data/json/items/comestibles/mre.json @@ -74129,7 +74370,7 @@ msgstr "一份軍用口糧的燉牛腩主菜, 能夠保存到近乎永遠。經 #: data/json/items/comestibles/mre.json msgid "meatballs & marinara entree" msgid_plural "meatballs & marinara entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(番茄酱肉丸)" #. ~ Description for meatballs & marinara entree #: data/json/items/comestibles/mre.json @@ -74141,7 +74382,7 @@ msgstr "一份軍用口糧的義式茄汁肉丸主菜, 能夠保存到近乎永 #: data/json/items/comestibles/mre.json msgid "beef stew entree" msgid_plural "beef stew entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(炖牛肉)" #. ~ Description for {'str': 'beef stew entree'} #: data/json/items/comestibles/mre.json @@ -74153,7 +74394,7 @@ msgstr "一份軍用口糧的燉牛肉主菜, 能夠保存到近乎永遠。經 #: data/json/items/comestibles/mre.json msgid "chili & macaroni entree" msgid_plural "chili & macaroni entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(辣椒通心粉)" #. ~ Description for chili & macaroni entree #: data/json/items/comestibles/mre.json @@ -74165,7 +74406,7 @@ msgstr "一份軍用口糧的辣味通心粉主菜, 能夠保存到近乎永遠 #: data/json/items/comestibles/mre.json msgid "vegetarian taco entree" msgid_plural "vegetarian taco entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(墨西哥素菜卷)" #. ~ Description for vegetarian taco entree #: data/json/items/comestibles/mre.json @@ -74177,7 +74418,7 @@ msgstr "一份軍用口糧的蔬菜塔可餅主菜, 能夠保存到近乎永遠 #: data/json/items/comestibles/mre.json msgid "macaroni & marinara entree" msgid_plural "macaroni & marinara entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(番茄酱通心粉)" #. ~ Description for macaroni & marinara entree #: data/json/items/comestibles/mre.json @@ -74189,7 +74430,7 @@ msgstr "一份軍用口糧的義式茄汁肉丸主菜, 能夠保存到近乎永 #: data/json/items/comestibles/mre.json msgid "cheese tortellini entree" msgid_plural "cheese tortellini entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(芝士水饺)" #. ~ Description for cheese tortellini entree #: data/json/items/comestibles/mre.json @@ -74201,7 +74442,7 @@ msgstr "一份軍用口糧的義大利起司餃,能夠保存到近乎永遠。 #: data/json/items/comestibles/mre.json msgid "mushroom fettuccine entree" msgid_plural "mushroom fettuccine entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(蘑菇意大利宽面)" #. ~ Description for mushroom fettuccine entree #: data/json/items/comestibles/mre.json @@ -74213,7 +74454,7 @@ msgstr "一份軍用口糧的蘑菇義大利細麵主菜, 能夠保存到近乎 #: data/json/items/comestibles/mre.json msgid "Mexican chicken stew entree" msgid_plural "Mexican chicken stew entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(墨西哥炖鸡肉)" #. ~ Description for {'str': 'Mexican chicken stew entree'} #: data/json/items/comestibles/mre.json @@ -74225,7 +74466,7 @@ msgstr "一份軍用口糧的墨西哥燉雞主菜, 能夠保存到近乎永遠 #: data/json/items/comestibles/mre.json msgid "chicken burrito bowl entree" msgid_plural "chicken burrito bowl entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(墨西哥鸡肉沙拉)" #. ~ Description for chicken burrito bowl entree #: data/json/items/comestibles/mre.json @@ -74237,7 +74478,7 @@ msgstr "一份軍用口糧的雞肉捲餅餐主菜, 能夠保存到近乎永 #: data/json/items/comestibles/mre.json msgid "maple sausage entree" msgid_plural "maple sausage entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(枫糖香肠)" #. ~ Description for maple sausage entree #: data/json/items/comestibles/mre.json @@ -74249,7 +74490,7 @@ msgstr "一份軍用口糧的楓糖香腸主菜。使用輻射滅菌,因此可 #: data/json/items/comestibles/mre.json msgid "ravioli entree" msgid_plural "ravioli entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(意式方饺)" #. ~ Description for ravioli entree #: data/json/items/comestibles/mre.json @@ -74261,7 +74502,7 @@ msgstr "一份軍用口糧的餛飩主菜, 能夠保存到近乎永遠。經 #: data/json/items/comestibles/mre.json msgid "pepper jack beef entree" msgid_plural "pepper jack beef entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(胡椒杰克芝士牛肉)" #. ~ Description for pepper jack beef entree #: data/json/items/comestibles/mre.json @@ -74273,7 +74514,7 @@ msgstr "一份軍用口糧的B傑克起司牛肉主菜, 能夠保存到近乎 #: data/json/items/comestibles/mre.json msgid "hash browns & bacon entree" msgid_plural "hash browns & bacon entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(洋葱土豆煎饼配培根)" #. ~ Description for hash browns & bacon entree #: data/json/items/comestibles/mre.json @@ -74285,7 +74526,7 @@ msgstr "一份軍用口糧的培根薯餅主菜, 能夠保存到近乎永遠。 #: data/json/items/comestibles/mre.json msgid "lemon pepper tuna entree" msgid_plural "lemon pepper tuna entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(柠檬胡椒金枪鱼)" #. ~ Description for lemon pepper tuna entree #: data/json/items/comestibles/mre.json @@ -74297,7 +74538,7 @@ msgstr "一份軍用口糧的檸檬胡椒鮪魚主菜, 能夠保存到近乎 #: data/json/items/comestibles/mre.json msgid "asian beef & vegetables entree" msgid_plural "asian beef & vegetables entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(亚式牛肉炒菜)" #. ~ Description for {'str': 'asian beef & vegetables entree'} #: data/json/items/comestibles/mre.json @@ -74309,7 +74550,7 @@ msgstr "一份軍用口糧的亞洲風味牛肉佐蔬菜。使用輻射滅菌, #: data/json/items/comestibles/mre.json msgid "chicken pesto & pasta entree" msgid_plural "chicken pesto & pasta entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(鸡肉意大利香蒜沙司通心粉)" #. ~ Description for chicken pesto & pasta entree #: data/json/items/comestibles/mre.json @@ -74321,7 +74562,7 @@ msgstr "一份軍用口糧的雞肉香蒜醬和義大利麵,能夠保存到近 #: data/json/items/comestibles/mre.json msgid "southwest beef & beans entree" msgid_plural "southwest beef & beans entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(西南牛肉炖豆)" #. ~ Description for southwest beef & beans entree #: data/json/items/comestibles/mre.json @@ -74333,7 +74574,7 @@ msgstr "一份MRE军用口粮的西南牛肉炖豆风味主菜。已经经过辐 #: data/json/items/comestibles/mre.json msgid "frankfurters & beans entree" msgid_plural "frankfurters & beans entrees" -msgstr[0] "" +msgstr[0] "MRE 主菜(法兰克福香肠炖豆)" #. ~ Description for frankfurters & beans entree #: data/json/items/comestibles/mre.json @@ -74346,7 +74587,7 @@ msgstr "一份軍用口糧的法蘭克福香腸佐豌豆, 能夠保存到近 #: data/json/items/comestibles/mushroom.json msgid "cooked mushroom" msgid_plural "cooked mushrooms" -msgstr[0] "" +msgstr[0] "炖蘑菇" #. ~ Description for cooked mushroom #: data/json/items/comestibles/mushroom.json @@ -74357,7 +74598,7 @@ msgstr "美味的野生蘑菇, 已經煮熟了。" #: data/json/items/comestibles/seed.json msgid "morel mushroom" msgid_plural "morel mushrooms" -msgstr[0] "" +msgstr[0] "羊肚菌" #. ~ Description for morel mushroom #: data/json/items/comestibles/mushroom.json @@ -74369,7 +74610,7 @@ msgstr "不只是廚師, 連樵夫都珍視的美味羊肚菌, 但最好先煮 #: data/json/items/comestibles/mushroom.json msgid "cooked morel mushroom" msgid_plural "cooked morel mushrooms" -msgstr[0] "" +msgstr[0] "炖羊肚菌" #. ~ Description for cooked morel mushroom #: data/json/items/comestibles/mushroom.json @@ -74379,7 +74620,7 @@ msgstr "美味的熟羊肚菌。" #: data/json/items/comestibles/mushroom.json msgid "fried morel mushroom" msgid_plural "fried morel mushrooms" -msgstr[0] "" +msgstr[0] "炒羊肚菌" #. ~ Description for fried morel mushroom #: data/json/items/comestibles/mushroom.json @@ -74389,7 +74630,7 @@ msgstr "一份美味的炒羊肚菌。" #: data/json/items/comestibles/mushroom.json msgid "dried mushroom" msgid_plural "dried mushrooms" -msgstr[0] "" +msgstr[0] "干蘑菇" #. ~ Description for dried mushroom #: data/json/items/comestibles/mushroom.json @@ -74400,7 +74641,7 @@ msgstr "香菇乾美味又健康, 此外還有許多料理方式。" #: data/json/items/comestibles/seed.json msgid "mushroom" msgid_plural "mushrooms" -msgstr[0] "" +msgstr[0] "蘑菇" #. ~ Description for mushroom #: data/json/items/comestibles/mushroom.json @@ -74412,7 +74653,7 @@ msgstr "蘑菇雖然很美味, 但小心。某些會讓你中毒, 或是產生 #: data/json/items/comestibles/mutagen.json msgid "abstract mutagen flavor" msgid_plural "abstract mutagen flavors" -msgstr[0] "" +msgstr[0] "虚拟诱变剂风味" #. ~ Description for {'str': 'abstract mutagen flavor'} #: data/json/items/comestibles/mutagen.json @@ -74422,7 +74663,7 @@ msgstr "來自不明來源的藥劑, 飲用它可以讓人產生突變。" #: data/json/items/comestibles/mutagen.json msgid "abstract iv mutagen flavor" msgid_plural "abstract iv mutagen flavors" -msgstr[0] "" +msgstr[0] "虚拟IV诱变剂风味" #. ~ Description for {'str': 'abstract iv mutagen flavor'} #: data/json/items/comestibles/mutagen.json @@ -74434,12 +74675,12 @@ msgstr "超浓缩的诱变剂。你需要针管注射器来将其注入体内… #: data/json/items/comestibles/mutagen.json msgid "mutagenic serum" msgid_plural "mutagenic serums" -msgstr[0] "" +msgstr[0] "诱变血清" #: data/json/items/comestibles/mutagen.json msgid "alpha serum" msgid_plural "alpha serum" -msgstr[0] "" +msgstr[0] "新人类诱变血清" #. ~ Description for {'str_sp': 'alpha serum'} #: data/json/items/comestibles/mutagen.json @@ -74451,7 +74692,7 @@ msgstr "超浓缩的诱变剂,看上去就像鲜血一样。你需要一个针 #: data/json/items/comestibles/mutagen.json msgid "beast serum" msgid_plural "beast serums" -msgstr[0] "" +msgstr[0] "野兽诱变血清" #. ~ Description for {'str': 'beast serum'} #: data/json/items/comestibles/mutagen.json @@ -74463,7 +74704,7 @@ msgstr "超浓缩的诱变剂,像斗牛士的斗篷一样红。你需要一根 #: data/json/items/comestibles/mutagen.json msgid "bird serum" msgid_plural "bird serums" -msgstr[0] "" +msgstr[0] "鸟类诱变血清" #. ~ Description for {'str': 'bird serum'} #: data/json/items/comestibles/mutagen.json @@ -74475,7 +74716,7 @@ msgstr "超浓缩的诱变剂,那种蓝色让你想起了大灾变之前的天 #: data/json/items/comestibles/mutagen.json msgid "cattle serum" msgid_plural "cattle serums" -msgstr[0] "" +msgstr[0] "家畜诱变血清" #. ~ Description for cattle serum #: data/json/items/comestibles/mutagen.json @@ -74487,7 +74728,7 @@ msgstr "超浓缩的诱变剂,有着一种青草的颜色。你需要一个针 #: data/json/items/comestibles/mutagen.json msgid "cephalopod serum" msgid_plural "cephalopod serums" -msgstr[0] "" +msgstr[0] "章鱼诱变血清" #. ~ Description for cephalopod serum #: data/json/items/comestibles/mutagen.json @@ -74499,7 +74740,7 @@ msgstr "超浓缩的诱变剂,像墨水一样黑。你需要一根针管来注 #: data/json/items/comestibles/mutagen.json msgid "chimera serum" msgid_plural "chimera serums" -msgstr[0] "" +msgstr[0] "奇美拉诱变血清" #. ~ Description for chimera serum #: data/json/items/comestibles/mutagen.json @@ -74511,7 +74752,7 @@ msgstr "超浓缩的诱变剂,呈现出搅动在一起的彩虹色。你需要 #: data/json/items/comestibles/mutagen.json msgid "elf-a serum" msgid_plural "elf-a serums" -msgstr[0] "" +msgstr[0] "精灵诱变血清" #. ~ Description for elf-a serum #: data/json/items/comestibles/mutagen.json @@ -74523,7 +74764,7 @@ msgstr "超浓缩的诱变剂,呈现出惹人注目的森林绿色。你需要 #: data/json/items/comestibles/mutagen.json msgid "feline serum" msgid_plural "feline serums" -msgstr[0] "" +msgstr[0] "猫科诱变血清" #. ~ Description for feline serum #: data/json/items/comestibles/mutagen.json @@ -74535,7 +74776,7 @@ msgstr "超浓缩的诱变剂,呈现黄色并且高度反光。你需要一根 #: data/json/items/comestibles/mutagen.json msgid "fish serum" msgid_plural "fish serums" -msgstr[0] "" +msgstr[0] "鱼类诱变血清" #. ~ Description for fish serum #: data/json/items/comestibles/mutagen.json @@ -74547,7 +74788,7 @@ msgstr "超浓缩的诱变剂,有着大海一般深邃的蓝色,顶部浮着 #: data/json/items/comestibles/mutagen.json msgid "insect serum" msgid_plural "insect serums" -msgstr[0] "" +msgstr[0] "昆虫诱变血清" #. ~ Description for insect serum #: data/json/items/comestibles/mutagen.json @@ -74559,7 +74800,7 @@ msgstr "超浓缩的诱变剂,呈现出美丽的琥珀色。你需要一根针 #: data/json/items/comestibles/mutagen.json msgid "lizard serum" msgid_plural "lizard serums" -msgstr[0] "" +msgstr[0] "蜥蜴诱变血清" #. ~ Description for lizard serum #: data/json/items/comestibles/mutagen.json @@ -74571,7 +74812,7 @@ msgstr "超浓缩的诱变剂,在不同深浅的绿色之间变幻。你需要 #: data/json/items/comestibles/mutagen.json msgid "lupine serum" msgid_plural "lupine serums" -msgstr[0] "" +msgstr[0] "狼类诱变血清" #. ~ Description for lupine serum #: data/json/items/comestibles/mutagen.json @@ -74583,7 +74824,7 @@ msgstr "超浓缩的诱变剂,如满月一般皎白。你需要一根针管来 #: data/json/items/comestibles/mutagen.json msgid "medical serum" msgid_plural "medical serums" -msgstr[0] "" +msgstr[0] "医学诱变血清" #. ~ Description for medical serum #: data/json/items/comestibles/mutagen.json @@ -74595,7 +74836,7 @@ msgstr "超浓缩的诱变剂,看上去像是各种体液的混合物。你需 #: data/json/items/comestibles/mutagen.json msgid "plant serum" msgid_plural "plant serums" -msgstr[0] "" +msgstr[0] "植物诱变血清" #. ~ Description for plant serum #: data/json/items/comestibles/mutagen.json @@ -74607,7 +74848,7 @@ msgstr "超浓缩的诱变剂,看上去像是一堆菠菜糊糊。你需要一 #: data/json/items/comestibles/mutagen.json msgid "raptor serum" msgid_plural "raptor serums" -msgstr[0] "" +msgstr[0] "迅猛龙诱变血清" #. ~ Description for raptor serum #: data/json/items/comestibles/mutagen.json @@ -74619,7 +74860,7 @@ msgstr "超浓缩的诱变剂,每次当你看它时似乎都会有所变化。 #: data/json/items/comestibles/mutagen.json msgid "rat serum" msgid_plural "rat serums" -msgstr[0] "" +msgstr[0] "大鼠诱变血清" #. ~ Description for rat serum #: data/json/items/comestibles/mutagen.json @@ -74631,7 +74872,7 @@ msgstr "超浓缩的诱变剂,看上去呈现出毫无吸引力的米黄色。 #: data/json/items/comestibles/mutagen.json msgid "slime serum" msgid_plural "slime serums" -msgstr[0] "" +msgstr[0] "变形怪诱变血清" #. ~ Description for slime serum #: data/json/items/comestibles/mutagen.json @@ -74643,7 +74884,7 @@ msgstr "超浓缩的诱变剂,看起来就像丧尸眼睛里黑色的粘液。 #: data/json/items/comestibles/mutagen.json msgid "spider serum" msgid_plural "spider serums" -msgstr[0] "" +msgstr[0] "蜘蛛诱变血清" #. ~ Description for spider serum #: data/json/items/comestibles/mutagen.json @@ -74655,7 +74896,7 @@ msgstr "超浓缩的诱变剂,里面隐约悬浮着一些白色的丝状物。 #: data/json/items/comestibles/mutagen.json msgid "troglobite serum" msgid_plural "troglobite serums" -msgstr[0] "" +msgstr[0] "穴居诱变血清" #. ~ Description for troglobite serum #: data/json/items/comestibles/mutagen.json @@ -74667,7 +74908,7 @@ msgstr "超浓缩的诱变剂,看起来有点畏惧光线。你需要一个针 #: data/json/items/comestibles/mutagen.json msgid "ursine serum" msgid_plural "ursine serums" -msgstr[0] "" +msgstr[0] "熊科诱变血清" #. ~ Description for ursine serum #: data/json/items/comestibles/mutagen.json @@ -74679,7 +74920,7 @@ msgstr "超浓缩的诱变剂,蜂蜜一样的颜色,蜂蜜一般的浓稠。 #: data/json/items/comestibles/mutagen.json msgid "mouse serum" msgid_plural "mouse serums" -msgstr[0] "" +msgstr[0] "小鼠诱变血清" #. ~ Description for mouse serum #: data/json/items/comestibles/mutagen.json @@ -74691,12 +74932,12 @@ msgstr "超浓缩的诱变剂,看上去就像液态金属一样。你需要一 #: data/json/items/comestibles/mutagen.json msgid "mutagen" msgid_plural "mutagens" -msgstr[0] "" +msgstr[0] "诱变剂" #: data/json/items/comestibles/mutagen.json msgid "congealed blood" msgid_plural "congealed bloods" -msgstr[0] "" +msgstr[0] "凝结之血" #. ~ Description for congealed blood #: data/json/items/comestibles/mutagen.json @@ -74708,7 +74949,7 @@ msgstr "浓稠黏糊的红色液体。看着闻着都恶心,而且仿佛有生 #: data/json/items/comestibles/mutagen.json msgid "alpha mutagen" msgid_plural "alpha mutagen" -msgstr[0] "" +msgstr[0] "新人类诱变剂" #. ~ Description for {'str_sp': 'alpha mutagen'} #. ~ Description for chimera mutagen @@ -74721,107 +74962,107 @@ msgstr "一種非常稀有的混和突變劑。" #: data/json/items/comestibles/mutagen.json msgid "beast mutagen" msgid_plural "beast mutagens" -msgstr[0] "" +msgstr[0] "野兽诱变剂" #: data/json/items/comestibles/mutagen.json msgid "bird mutagen" msgid_plural "bird mutagens" -msgstr[0] "" +msgstr[0] "鸟类诱变剂" #: data/json/items/comestibles/mutagen.json msgid "cattle mutagen" msgid_plural "cattle mutagens" -msgstr[0] "" +msgstr[0] "家畜诱变剂" #: data/json/items/comestibles/mutagen.json msgid "cephalopod mutagen" msgid_plural "cephalopod mutagens" -msgstr[0] "" +msgstr[0] "章鱼诱变剂" #: data/json/items/comestibles/mutagen.json msgid "chimera mutagen" msgid_plural "chimera mutagens" -msgstr[0] "" +msgstr[0] "奇美拉诱变剂" #: data/json/items/comestibles/mutagen.json msgid "elf-a mutagen" msgid_plural "elf-a mutagens" -msgstr[0] "" +msgstr[0] "精灵诱变剂" #: data/json/items/comestibles/mutagen.json msgid "feline mutagen" msgid_plural "feline mutagens" -msgstr[0] "" +msgstr[0] "猫科诱变剂" #: data/json/items/comestibles/mutagen.json msgid "fish mutagen" msgid_plural "fish mutagens" -msgstr[0] "" +msgstr[0] "鱼类诱变剂" #: data/json/items/comestibles/mutagen.json msgid "insect mutagen" msgid_plural "insect mutagens" -msgstr[0] "" +msgstr[0] "昆虫诱变剂" #: data/json/items/comestibles/mutagen.json msgid "lizard mutagen" msgid_plural "lizard mutagens" -msgstr[0] "" +msgstr[0] "蜥蜴诱变剂" #: data/json/items/comestibles/mutagen.json msgid "lupine mutagen" msgid_plural "lupine mutagens" -msgstr[0] "" +msgstr[0] "狼类诱变剂" #: data/json/items/comestibles/mutagen.json msgid "medical mutagen" msgid_plural "medical mutagens" -msgstr[0] "" +msgstr[0] "医学诱变剂" #: data/json/items/comestibles/mutagen.json msgid "plant mutagen" msgid_plural "plant mutagens" -msgstr[0] "" +msgstr[0] "植物诱变剂" #: data/json/items/comestibles/mutagen.json msgid "raptor mutagen" msgid_plural "raptor mutagens" -msgstr[0] "" +msgstr[0] "迅猛龙诱变剂" #: data/json/items/comestibles/mutagen.json msgid "rat mutagen" msgid_plural "rat mutagens" -msgstr[0] "" +msgstr[0] "大鼠诱变剂" #: data/json/items/comestibles/mutagen.json msgid "slime mutagen" msgid_plural "slime mutagens" -msgstr[0] "" +msgstr[0] "变形怪诱变剂" #: data/json/items/comestibles/mutagen.json msgid "spider mutagen" msgid_plural "spider mutagens" -msgstr[0] "" +msgstr[0] "蜘蛛诱变剂" #: data/json/items/comestibles/mutagen.json msgid "troglobite mutagen" msgid_plural "troglobite mutagens" -msgstr[0] "" +msgstr[0] "穴居诱变剂" #: data/json/items/comestibles/mutagen.json msgid "ursine mutagen" msgid_plural "ursine mutagens" -msgstr[0] "" +msgstr[0] "熊科诱变剂" #: data/json/items/comestibles/mutagen.json msgid "mouse mutagen" msgid_plural "mouse mutagens" -msgstr[0] "" +msgstr[0] "小鼠诱变剂" #: data/json/items/comestibles/mutagen.json msgid "purifier" msgid_plural "purifiers" -msgstr[0] "" +msgstr[0] "净化剂" #. ~ Description for purifier #: data/json/items/comestibles/mutagen.json @@ -74833,7 +75074,7 @@ msgstr "一種罕見的幹細胞治療劑, 可以使突變與其他遺傳性疾 #: data/json/items/comestibles/mutagen.json msgid "purifier serum" msgid_plural "purifier serums" -msgstr[0] "" +msgstr[0] "净化血清" #. ~ Description for purifier serum #: data/json/items/comestibles/mutagen.json @@ -74844,7 +75085,7 @@ msgstr "一個超濃縮的幹細胞治療劑。你需要一個針筒才能注射 #: data/json/items/comestibles/mutagen.json msgid "purifier smart shot" msgid_plural "purifier smart shots" -msgstr[0] "" +msgstr[0] "智能净化血清" #. ~ Description for purifier smart shot #: data/json/items/comestibles/mutagen.json @@ -74869,7 +75110,7 @@ msgstr "一個畸形的人類胚胎,吃這個是你所能想到最噁心的事 #: data/json/items/comestibles/mutagen.json msgid "mutated arm" msgid_plural "mutated arms" -msgstr[0] "" +msgstr[0] "变异手臂" #. ~ Description for {'str': 'mutated arm'} #: data/json/items/comestibles/mutagen.json @@ -74881,7 +75122,7 @@ msgstr "一隻畸形的人類手臂,吃下這個會非常噁心,並且可能 #: data/json/items/comestibles/mutagen.json msgid "mutated leg" msgid_plural "mutated legs" -msgstr[0] "" +msgstr[0] "变异大腿" #. ~ Description for mutated leg #: data/json/items/comestibles/mutagen.json @@ -74893,7 +75134,7 @@ msgstr "一隻畸形的人類大腿,吃下這個會非常反胃,並且可能 #: data/json/items/comestibles/mutagen.json msgid "tainted tornado" msgid_plural "tainted tornados" -msgstr[0] "" +msgstr[0] "感染龙卷风" #. ~ Description for tainted tornado #: data/json/items/comestibles/mutagen.json @@ -74905,7 +75146,7 @@ msgstr "一种被发泡的浆状的酒精浸泡的丧尸烂血肉,它闻起来 #: data/json/items/comestibles/mutagen.json msgid "sewer brew" msgid_plural "sewer brews" -msgstr[0] "" +msgstr[0] "水道酿" #. ~ Description for sewer brew #: data/json/items/comestibles/mutagen.json @@ -75138,7 +75379,7 @@ msgstr "一把來自山核桃樹的烘烤山核桃。" #: data/json/items/comestibles/nuts.json msgid "hickory nut ambrosia" msgid_plural "hickory nut ambrosias" -msgstr[0] "" +msgstr[0] "山核桃酿" #. ~ Description for hickory nut ambrosia #: data/json/items/comestibles/nuts.json @@ -75170,7 +75411,7 @@ msgstr "一把從橡樹摘下的的堅果, 已經烤過。" #: data/json/items/comestibles/nuts.json msgid "cooked acorn meal" msgid_plural "cooked acorn meal" -msgstr[0] "" +msgstr[0] "煮橡子面" #. ~ Description for {'str_sp': 'cooked acorn meal'} #: data/json/items/comestibles/nuts.json @@ -75203,7 +75444,7 @@ msgstr "傳統的肝臟料理法" #: data/json/items/comestibles/offal_dishes.json msgid "fried liver" msgid_plural "fried livers" -msgstr[0] "" +msgstr[0] "炸肝" #. ~ Description for fried liver #. ~ Description for deep-fried tripe @@ -75214,7 +75455,7 @@ msgstr "沒有什麼比油炸的東西更美味!" #: data/json/items/comestibles/offal_dishes.json msgid "humble pie" msgid_plural "humble pies" -msgstr[0] "" +msgstr[0] "内脏馅饼" #. ~ Description for humble pie #: data/json/items/comestibles/offal_dishes.json @@ -75226,7 +75467,7 @@ msgstr "也被稱為雜碎派,由切碎的動物內臟製成。沒有聽起來 #: data/json/items/comestibles/offal_dishes.json msgid "stewed tripe" msgid_plural "stewed tripes" -msgstr[0] "" +msgstr[0] "炖肚条" #. ~ Description for stewed tripe #: data/json/items/comestibles/offal_dishes.json @@ -75238,7 +75479,7 @@ msgstr "胃,切碎,放进汤里慢慢煨,吃起来比听起来更美味。 #: data/json/items/comestibles/offal_dishes.json msgid "deep-fried tripe" msgid_plural "deep-fried tripes" -msgstr[0] "" +msgstr[0] "油炸肚条" #: data/json/items/comestibles/offal_dishes.json msgid "leverpostej" @@ -75266,7 +75507,7 @@ msgstr "現在你可以模仿你喜愛的那些殭屍了! 烹調大腦是很 #: data/json/items/comestibles/offal_dishes.json msgid "fried brain" msgid_plural "fried brains" -msgstr[0] "" +msgstr[0] "油炸脑子" #. ~ Description for fried brain #: data/json/items/comestibles/offal_dishes.json @@ -75276,7 +75517,7 @@ msgstr "你可别对它抱太大期望了。只是被油炸了一遍。" #: data/json/items/comestibles/offal_dishes.json msgid "cooked kidney" msgid_plural "cooked kidneys" -msgstr[0] "" +msgstr[0] "熟肾" #. ~ Description for cooked kidney #: data/json/items/comestibles/offal_dishes.json @@ -75286,7 +75527,7 @@ msgstr "不,這不是豆子。" #: data/json/items/comestibles/offal_dishes.json msgid "deviled kidney" msgid_plural "deviled kidneys" -msgstr[0] "" +msgstr[0] "酱制腰子" #. ~ Description for deviled kidney #: data/json/items/comestibles/offal_dishes.json @@ -75296,7 +75537,7 @@ msgstr "腎臟的一種美味調理方式" #: data/json/items/comestibles/offal_dishes.json msgid "cooked sweetbread" msgid_plural "cooked sweetbreads" -msgstr[0] "" +msgstr[0] "熟杂碎" #. ~ Description for cooked sweetbread #: data/json/items/comestibles/offal_dishes.json @@ -75306,7 +75547,7 @@ msgstr "照理說應該很美味,但它還需要...一些東西調味。" #: data/json/items/comestibles/offal_dishes.json msgid "grilled sweetbread" msgid_plural "grilled sweetbreads" -msgstr[0] "" +msgstr[0] "煎杂碎" #. ~ Description for grilled sweetbread #: data/json/items/comestibles/offal_dishes.json @@ -75316,7 +75557,7 @@ msgstr "不如名字所暗示的那樣甜,但仍然美味!" #: data/json/items/comestibles/offal_dishes.json msgid "cooked liver" msgid_plural "cooked livers" -msgstr[0] "" +msgstr[0] "熟肝" #. ~ Description for cooked liver #: data/json/items/comestibles/offal_dishes.json @@ -75329,7 +75570,7 @@ msgstr "一块来自某种动物的肝脏。富含维生素B!煮熟的肝脏 #: data/json/items/comestibles/offal_dishes.json msgid "canned liver" msgid_plural "canned livers" -msgstr[0] "" +msgstr[0] "罐装肝脏" #. ~ Description for canned liver #: data/json/items/comestibles/offal_dishes.json @@ -75354,7 +75595,7 @@ msgstr "" #: data/json/items/comestibles/offal_dishes.json msgid "lung provence" msgid_plural "lung provences" -msgstr[0] "" +msgstr[0] "普罗旺斯香草肺片" #. ~ Description for lung provence #: data/json/items/comestibles/offal_dishes.json @@ -75364,7 +75605,7 @@ msgstr "一道美味的肺脏料理。" #: data/json/items/comestibles/offal_dishes.json msgid "toettchen" msgid_plural "toettchens" -msgstr[0] "" +msgstr[0] "内脏面包" #. ~ Description for toettchen #. ~ Description for tÖttchen @@ -75376,7 +75617,7 @@ msgstr "一道德国肺脏料理。" #: data/json/items/comestibles/offal_dishes.json msgid "scrambled eggs and brain" msgid_plural "scrambled eggs and brains" -msgstr[0] "" +msgstr[0] "脑花炒蛋" #. ~ Description for scrambled eggs and brain #: data/json/items/comestibles/offal_dishes.json @@ -75386,7 +75627,7 @@ msgstr "脑花加蛋,以前怎么就没想到把它们凑一对儿呢?" #: data/json/items/comestibles/offal_dishes.json msgid "sausage casing" msgid_plural "sausage casings" -msgstr[0] "" +msgstr[0] "肠衣" #. ~ Description for {'str': 'sausage casing'} #: data/json/items/comestibles/offal_dishes.json @@ -75398,26 +75639,26 @@ msgstr "用动物的肠子制成的肠衣,可以用来装香肠。" #: data/json/items/comestibles/offal_dishes.json msgid "homemade hot dog" msgid_plural "homemade hot dogs" -msgstr[0] "" +msgstr[0] "自制热狗" #: data/json/items/comestibles/offal_dishes.json msgid "fried offal" msgid_plural "fried offal" -msgstr[0] "" +msgstr[0] "炸内脏" #. ~ Conditional name for {'str_sp': 'fried offal'} when FLAG matches #. CANNIBALISM #: data/json/items/comestibles/offal_dishes.json msgid "fried Frank offal" msgid_plural "fried Frank offals" -msgstr[0] "" +msgstr[0] "炸人内脏" #. ~ Conditional name for {'str_sp': 'fried offal'} when COMPONENT_ID matches #. mutant #: data/json/items/comestibles/offal_dishes.json msgid "fried freak offal" msgid_plural "fried freak offal" -msgstr[0] "" +msgstr[0] "炸变异内脏" #. ~ Description for {'str_sp': 'fried offal'} #: data/json/items/comestibles/offal_dishes.json @@ -75430,7 +75671,7 @@ msgstr "这是新鲜烹制的器官肉和内脏。油炸使它更为可口,虽 #: data/json/items/comestibles/other.json msgid "diet pill" msgid_plural "diet pills" -msgstr[0] "" +msgstr[0] "减肥药" #. ~ Description for diet pill #: data/json/items/comestibles/other.json @@ -75442,7 +75683,7 @@ msgstr "不是很有營養。警告: 含有熱量, 不適合吃空氣存活的 #: data/json/items/comestibles/other.json msgid "blob glob" msgid_plural "blob globs" -msgstr[0] "" +msgstr[0] "变形怪糊" #. ~ Description for {'str': 'blob glob'} #: data/json/items/comestibles/other.json @@ -75454,7 +75695,7 @@ msgstr "一小塊從黏球怪身上掉下的黏液。雖然它偶爾會抽動, #: data/json/items/comestibles/other.json msgid "honey comb" msgid_plural "honey combs" -msgstr[0] "" +msgstr[0] "蜂巢块" #. ~ Description for honey comb #: data/json/items/comestibles/other.json @@ -75524,7 +75765,7 @@ msgstr "这看起来就像凝固住的柠檬色液体,活像末日前的果冻 #: data/json/items/comestibles/other.json data/mods/No_Fungi/comestibles.json msgid "mycus fruit" msgid_plural "mycus fruits" -msgstr[0] "" +msgstr[0] "马卡斯果" #. ~ Description for {'str': 'mycus fruit'} #: data/json/items/comestibles/other.json @@ -75537,7 +75778,7 @@ msgstr "人們也許會稱它為美味灰蘋果: 大、灰、聞起來甚至比 #: data/json/items/comestibles/other.json msgid "yeast" msgid_plural "yeast" -msgstr[0] "" +msgstr[0] "酵母" #. ~ Description for {'str_sp': 'yeast'} #: data/json/items/comestibles/other.json @@ -75548,7 +75789,7 @@ msgstr "粉狀的混合培養酵母, 適合用來烘焙和釀造。" #: data/json/items/comestibles/other.json msgid "bone meal" msgid_plural "bone meal" -msgstr[0] "" +msgstr[0] "骨粉" #. ~ Description for {'str_sp': 'bone meal'} #: data/json/items/comestibles/other.json @@ -75558,7 +75799,7 @@ msgstr "這些骨粉可以用來製作肥料或者其他東西。" #: data/json/items/comestibles/other.json msgid "tainted bone meal" msgid_plural "tainted bone meal" -msgstr[0] "" +msgstr[0] "被感染的骨粉" #. ~ Description for {'str_sp': 'tainted bone meal'} #: data/json/items/comestibles/other.json @@ -75579,7 +75820,7 @@ msgstr "這些甲殼粉可用來製作肥料或者其他東西。" #: data/json/items/comestibles/other.json msgid "cardboard" msgid_plural "cardboards" -msgstr[0] "" +msgstr[0] "硬纸板" #. ~ Description for cardboard #: data/json/items/comestibles/other.json @@ -75663,7 +75904,7 @@ msgstr "淡褐色的豆子,它們有很多用途,輕度有毒,不推薦, #: data/json/items/comestibles/other.json msgid "raw edamame" msgid_plural "raw edamames" -msgstr[0] "" +msgstr[0] "生毛豆" #. ~ Description for raw edamame #: data/json/items/comestibles/other.json @@ -75686,7 +75927,7 @@ msgstr "一種不起眼但營養豐富的豆類。應在食用前煮熟。" #: data/json/items/comestibles/other.json msgid "Foodplace's delicious food™" msgid_plural "Foodplace's delicious food™" -msgstr[0] "" +msgstr[0] "美食广场美食™" #. ~ Description for {'str_sp': "Foodplace's delicious food™"} #: data/json/items/comestibles/other.json @@ -75825,7 +76066,7 @@ msgstr "一些草叢,只能由食草動物和反芻動物食用。如果能看 #: data/json/items/comestibles/other.json msgid "nectar" msgid_plural "nectars" -msgstr[0] "" +msgstr[0] "花蜜" #. ~ Description for {'str': 'nectar'} #: data/json/items/comestibles/other.json @@ -75835,7 +76076,7 @@ msgstr "一些花蜜。看到這個的話就是有 bug。" #: data/json/items/comestibles/protein.json msgid "protein drink" msgid_plural "protein drinks" -msgstr[0] "" +msgstr[0] "蛋白饮料" #. ~ Conditional name for protein drink when FLAG matches CANNIBALISM #: data/json/items/comestibles/protein.json @@ -75853,7 +76094,7 @@ msgstr[0] "人肉蛋白飲料" #, c-format msgid "perturbing %s" msgid_plural "perturbing %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for protein drink #: data/json/items/comestibles/protein.json @@ -75884,7 +76125,7 @@ msgstr "精製過的蛋白粉! 雖然營養豐富, 但是不能直接食用, 試 #: data/json/items/comestibles/protein.json msgid "protein ration" msgid_plural "protein rations" -msgstr[0] "" +msgstr[0] "蛋白口粮" #. ~ Description for {'str': 'protein ration'} #: data/json/items/comestibles/protein.json @@ -75905,13 +76146,13 @@ msgstr "" #: data/json/items/comestibles/protein.json msgid "protein shake" msgid_plural "protein shakes" -msgstr[0] "" +msgstr[0] "蛋白混合饮料" #. ~ Conditional name for protein shake when FLAG matches CANNIBALISM #: data/json/items/comestibles/protein.json msgid "soylent green shake" msgid_plural "soylent green shakes" -msgstr[0] "" +msgstr[0] "人肉蛋白饮料" #. ~ Description for protein shake #: data/json/items/comestibles/protein.json @@ -75923,14 +76164,14 @@ msgstr "由濃厚的蛋白質糊與營養水果做成的風味飲料。" #: data/json/items/comestibles/protein.json msgid "fortified protein shake" msgid_plural "fortified protein shakes" -msgstr[0] "" +msgstr[0] "增强型蛋白混合饮料" #. ~ Conditional name for fortified protein shake when FLAG matches #. CANNIBALISM #: data/json/items/comestibles/protein.json msgid "fortified soylent green shake" msgid_plural "fortified soylent green shakes" -msgstr[0] "" +msgstr[0] "增强型人肉蛋白饮料" #. ~ Description for fortified protein shake #: data/json/items/comestibles/protein.json @@ -75942,7 +76183,7 @@ msgstr "由濃厚的蛋白質糊與營養水果做成的風味飲料。還進一 #: data/json/items/comestibles/raw_fruit.json msgid "apple" msgid_plural "apples" -msgstr[0] "" +msgstr[0] "苹果" #. ~ Description for {'str': 'apple'} #: data/json/items/comestibles/raw_fruit.json @@ -75953,7 +76194,7 @@ msgstr "一天一蘋果, 醫生遠離我。" #: data/mods/Aftershock/items/seed.json msgid "banana" msgid_plural "bananas" -msgstr[0] "" +msgstr[0] "香蕉" #. ~ Description for {'str': 'banana'} #: data/json/items/comestibles/raw_fruit.json @@ -75966,7 +76207,7 @@ msgstr "一根長而彎曲的黃色水果。有些人喜歡用這東西來做甜 #: data/mods/Aftershock/items/seed.json msgid "orange" msgid_plural "oranges" -msgstr[0] "" +msgstr[0] "橙子" #. ~ Description for orange #: data/json/items/comestibles/raw_fruit.json @@ -75977,7 +76218,7 @@ msgstr "甜味的圓形水果。也能做成果汁。" #: data/mods/Aftershock/items/seed.json msgid "lemon" msgid_plural "lemons" -msgstr[0] "" +msgstr[0] "柠檬" #. ~ Description for lemon #: data/json/items/comestibles/raw_fruit.json @@ -76069,7 +76310,7 @@ msgstr "這是授粉薔薇花的果實。" #: data/json/items/comestibles/raw_fruit.json msgid "juice pulp" msgid_plural "juice pulps" -msgstr[0] "" +msgstr[0] "果汁残渣" #. ~ Description for juice pulp #: data/json/items/comestibles/raw_fruit.json @@ -76081,7 +76322,7 @@ msgstr "水果榨汁後留下的殘渣。不是很好吃, 不過含有大量的 #: data/json/items/comestibles/raw_fruit.json msgid "pear" msgid_plural "pears" -msgstr[0] "" +msgstr[0] "梨子" #. ~ Description for pear #: data/json/items/comestibles/raw_fruit.json @@ -76091,7 +76332,7 @@ msgstr "多汁, 鐘形的梨子。好吃!" #: data/json/items/comestibles/raw_fruit.json msgid "grapefruit" msgid_plural "grapefruits" -msgstr[0] "" +msgstr[0] "西柚" #. ~ Description for grapefruit #: data/json/items/comestibles/raw_fruit.json @@ -76111,7 +76352,7 @@ msgstr "紅色甜味, 長在樹上的水果。" #: data/json/items/comestibles/raw_fruit.json msgid "plum" msgid_plural "plums" -msgstr[0] "" +msgstr[0] "李子" #. ~ Description for plum #: data/json/items/comestibles/raw_fruit.json @@ -76133,7 +76374,7 @@ msgstr "一串多汁的葡萄。" #: data/mods/Aftershock/items/seed.json msgid "pineapple" msgid_plural "pineapples" -msgstr[0] "" +msgstr[0] "菠萝" #. ~ Description for pineapple #: data/json/items/comestibles/raw_fruit.json @@ -76144,7 +76385,7 @@ msgstr "一個大而參差的鳳梨。有點酸。" #: data/mods/Aftershock/items/seed.json msgid "coconut" msgid_plural "coconuts" -msgstr[0] "" +msgstr[0] "椰子" #. ~ Description for coconut #: data/json/items/comestibles/raw_fruit.json @@ -76164,7 +76405,7 @@ msgstr "這水果的果核被許多美味的果肉包裹著。" #: data/json/items/comestibles/raw_fruit.json msgid "watermelon" msgid_plural "watermelons" -msgstr[0] "" +msgstr[0] "西瓜" #. ~ Description for watermelon #: data/json/items/comestibles/raw_fruit.json @@ -76175,7 +76416,7 @@ msgstr "一個水果, 比你的頭大。非常多汁!" #: data/mods/Aftershock/items/seed.json msgid "melon" msgid_plural "melons" -msgstr[0] "" +msgstr[0] "甜瓜" #. ~ Description for melon #: data/json/items/comestibles/raw_fruit.json @@ -76195,7 +76436,7 @@ msgstr "覆盆子的較黑近親。" #: data/json/items/comestibles/raw_fruit.json msgid "mango" msgid_plural "mangos" -msgstr[0] "" +msgstr[0] "芒果" #. ~ Description for mango #: data/json/items/comestibles/raw_fruit.json @@ -76205,7 +76446,7 @@ msgstr "有很大果核的新鮮水果。" #: data/json/items/comestibles/raw_fruit.json msgid "pomegranate" msgid_plural "pomegranates" -msgstr[0] "" +msgstr[0] "石榴" #. ~ Description for pomegranate #: data/json/items/comestibles/raw_fruit.json @@ -76215,7 +76456,7 @@ msgstr "在石榴的表皮之下有著數以百計的肉質種子。" #: data/json/items/comestibles/raw_fruit.json msgid "papaya" msgid_plural "papayas" -msgstr[0] "" +msgstr[0] "木瓜" #. ~ Description for papaya #: data/json/items/comestibles/raw_fruit.json @@ -76225,7 +76466,7 @@ msgstr "一個很甜, 果肉又柔軟的熱帶水果。" #: data/json/items/comestibles/raw_fruit.json msgid "kiwi" msgid_plural "kiwis" -msgstr[0] "" +msgstr[0] "猕猴桃" #. ~ Description for kiwi #: data/json/items/comestibles/raw_fruit.json @@ -76246,7 +76487,7 @@ msgstr "一種果皮光滑的水果, 桃子的近親。" #: data/json/items/comestibles/raw_fruit.json msgid "cholla bud" msgid_plural "cholla buds" -msgstr[0] "" +msgstr[0] "仙人掌花蕾" #. ~ Description for cholla bud #: data/json/items/comestibles/raw_fruit.json @@ -76258,7 +76499,7 @@ msgstr "可食用的仙人掌花蕾,刺已经去掉了,是莫哈维沙漠土 #: data/json/items/comestibles/raw_fruit.json msgid "cactus pad" msgid_plural "cactus pads" -msgstr[0] "" +msgstr[0] "食用仙人掌" #. ~ Description for cactus pad #: data/json/items/comestibles/raw_fruit.json @@ -76269,7 +76510,7 @@ msgstr "可食用的仙人掌莖葉。" #: data/json/items/comestibles/seed.json msgid "barley" msgid_plural "barleys" -msgstr[0] "" +msgstr[0] "大麦" #. ~ Description for {'str': 'barley'} #: data/json/items/comestibles/raw_veggy.json @@ -76282,7 +76523,7 @@ msgstr "顆粒狀的穀物。常用做為釀酒的原料。它也可以被磨成 #: data/json/items/comestibles/seed.json msgid "bee balm" msgid_plural "bee balms" -msgstr[0] "" +msgstr[0] "香蜂草" #. ~ Description for {'str': 'bee balm'} #: data/json/items/comestibles/raw_veggy.json @@ -76318,7 +76559,7 @@ msgstr "野生的蕎麥種子。不太適合直接生吃, 通常會煮過或者 #: data/json/items/comestibles/seed.json msgid "cabbage" msgid_plural "cabbages" -msgstr[0] "" +msgstr[0] "卷心菜" #. ~ Description for cabbage #: data/json/items/comestibles/raw_veggy.json @@ -76351,7 +76592,7 @@ msgstr "一束菠菜葉。" #: data/json/items/comestibles/seed.json msgid "carrot" msgid_plural "carrots" -msgstr[0] "" +msgstr[0] "胡萝卜" #. ~ Description for {'str': 'carrot'} #: data/json/items/comestibles/raw_veggy.json @@ -76361,7 +76602,7 @@ msgstr "一個健康的根類蔬菜。富含維他命 A!" #: data/json/items/comestibles/raw_veggy.json msgid "cattail rhizome" msgid_plural "cattail rhizomes" -msgstr[0] "" +msgstr[0] "香蒲根茎" #. ~ Description for {'str': 'cattail rhizome'} #: data/json/items/comestibles/raw_veggy.json @@ -76374,7 +76615,7 @@ msgstr "香蒲植物的粗壯根莖。白色果肉富含澱粉和纖維, 但不 #: data/json/items/comestibles/raw_veggy.json msgid "cattail stalk" msgid_plural "cattail stalks" -msgstr[0] "" +msgstr[0] "香蒲秆" #. ~ Description for {'str': 'cattail stalk'} #: data/json/items/comestibles/raw_veggy.json @@ -76387,7 +76628,7 @@ msgstr "香蒲植物堅硬的綠色秸稈。由澱粉和纖維組成, 如果煮 #: data/json/items/comestibles/seed.json msgid "celery" msgid_plural "celerys" -msgstr[0] "" +msgstr[0] "芹菜" #. ~ Description for celery #: data/json/items/comestibles/raw_veggy.json @@ -76409,7 +76650,7 @@ msgstr "美味的黃金蔬菜。" #: data/json/items/comestibles/raw_veggy.json msgid "cotton boll" msgid_plural "cotton bolls" -msgstr[0] "" +msgstr[0] "棉桃" #. ~ Description for {'str': 'cotton boll'} #: data/json/items/comestibles/raw_veggy.json @@ -76422,7 +76663,7 @@ msgstr "一個鼓鼓的果莢中塞著滿滿的棉花和種子, 用合適的工 #: data/json/items/comestibles/seed.json msgid "chili pepper" msgid_plural "chili peppers" -msgstr[0] "" +msgstr[0] "辣椒" #. ~ Description for chili pepper #: data/json/items/comestibles/raw_veggy.json @@ -76433,7 +76674,7 @@ msgstr "很辣的辣椒。" #: data/json/items/comestibles/seed.json msgid "cucumber" msgid_plural "cucumbers" -msgstr[0] "" +msgstr[0] "黄瓜" #. ~ Description for cucumber #: data/json/items/comestibles/raw_veggy.json @@ -76443,7 +76684,7 @@ msgstr "葫蘆科植物,沒什麼味道但是非常多汁。" #: data/json/items/comestibles/raw_veggy.json msgid "dahlia root" msgid_plural "dahlia roots" -msgstr[0] "" +msgstr[0] "大丽花根" #. ~ Description for dahlia root #: data/json/items/comestibles/raw_veggy.json @@ -76476,7 +76717,7 @@ msgstr "一朵藍色的小花。花的根非常苦,不應該生吃。" #: data/json/items/comestibles/seed.json msgid "wild root" msgid_plural "wild roots" -msgstr[0] "" +msgstr[0] "野生根茎" #. ~ Description for {'str': 'wild root'} #: data/json/items/comestibles/raw_veggy.json @@ -76489,7 +76730,7 @@ msgstr "有著叢生白色小花的草。這些通常是野胡蘿蔔,但要小 #: data/json/items/comestibles/seed.json msgid "dogbane" msgid_plural "dogbanes" -msgstr[0] "" +msgstr[0] "罗布麻" #. ~ Description for dogbane #: data/json/items/comestibles/raw_veggy.json @@ -76500,7 +76741,7 @@ msgstr "一條毒狗草的莖, 它具有非常多的纖維質和輕微的毒性 #: data/json/items/comestibles/raw_veggy.json msgid "garlic bulb" msgid_plural "garlic bulbs" -msgstr[0] "" +msgstr[0] "蒜头" #. ~ Description for garlic bulb #: data/json/items/comestibles/raw_veggy.json @@ -76522,7 +76763,7 @@ msgstr "一小朵錐狀的花, 釀造啤酒的必備材料。" #: data/json/items/comestibles/raw_veggy.json msgid "horseradish root" msgid_plural "horseradish roots" -msgstr[0] "" +msgstr[0] "辣根根茎" #. ~ Description for {'str': 'horseradish root'} #: data/json/items/comestibles/raw_veggy.json @@ -76535,7 +76776,7 @@ msgstr "一根巨大的白色锥形辣根根茎。这样直接吃太辣了,但 #: data/json/items/comestibles/seed.json msgid "lettuce" msgid_plural "lettuces" -msgstr[0] "" +msgstr[0] "莴苣" #. ~ Description for lettuce #: data/json/items/comestibles/raw_veggy.json @@ -76546,7 +76787,7 @@ msgstr "一個鮮嫩的捲心萵苣。" #: data/json/items/comestibles/seed.json msgid "mugwort" msgid_plural "mugworts" -msgstr[0] "" +msgstr[0] "艾草" #. ~ Description for mugwort #: data/json/items/comestibles/raw_veggy.json @@ -76557,7 +76798,7 @@ msgstr "一條艾草的莖。聞起來很棒。" #: data/json/items/comestibles/seed.json msgid "onion" msgid_plural "onions" -msgstr[0] "" +msgstr[0] "洋葱" #. ~ Description for onion #: data/json/items/comestibles/raw_veggy.json @@ -76569,7 +76810,7 @@ msgstr "烹飪時常用到的洋蔥。切割這個東西會讓你的眼睛刺痛 #: data/json/items/comestibles/raw_veggy.json msgid "fungal fluid sac" msgid_plural "fungal fluid sacs" -msgstr[0] "" +msgstr[0] "真菌液囊" #. ~ Description for fungal fluid sac #: data/json/items/comestibles/raw_veggy.json @@ -76581,7 +76822,7 @@ msgstr "一個真菌生物的液體水囊。不是很營養,反正能吃就對 #: data/json/items/comestibles/raw_veggy.json msgid "raw popcorn" msgid_plural "raw popcorn" -msgstr[0] "" +msgstr[0] "爆米花玉米" #. ~ Description for {'str_sp': 'raw popcorn'} #: data/json/items/comestibles/raw_veggy.json @@ -76604,7 +76845,7 @@ msgstr "生的時候有輕微毒性且不好吃。煮熟後將會很美味。" #: data/json/items/comestibles/seed.json msgid "pumpkin" msgid_plural "pumpkins" -msgstr[0] "" +msgstr[0] "南瓜" #. ~ Description for pumpkin #: data/json/items/comestibles/raw_veggy.json @@ -76616,7 +76857,7 @@ msgstr "一個大型蔬菜, 有你的頭那麼大。生的時候不怎麼好吃, #: data/json/items/comestibles/raw_veggy.json msgid "horseradish greens" msgid_plural "horseradish greens" -msgstr[0] "" +msgstr[0] "辣根叶" #. ~ Description for {'str_sp': 'horseradish greens'} #: data/json/items/comestibles/raw_veggy.json @@ -76640,7 +76881,7 @@ msgstr "一把新鮮的黃色蒲公英, 在他們還是原料的時候相當的 #: data/json/items/comestibles/raw_veggy.json msgid "burdocks" msgid_plural "burdocks" -msgstr[0] "" +msgstr[0] "牛蒡" #. ~ Description for {'str_sp': 'burdocks'} #: data/json/items/comestibles/raw_veggy.json @@ -76651,7 +76892,7 @@ msgstr "牛蒡,一种苦涩的蓟类蔬菜。可以生吃或煮熟。" #: data/json/items/comestibles/seed.json msgid "rhubarb" msgid_plural "rhubarbs" -msgstr[0] "" +msgstr[0] "大黄" #. ~ Description for rhubarb #: data/json/items/comestibles/raw_veggy.json @@ -76662,7 +76903,7 @@ msgstr "酸酸大黃菜, 通常用於烤餡餅。" #: data/json/items/comestibles/seed.json msgid "sugar beet" msgid_plural "sugar beets" -msgstr[0] "" +msgstr[0] "甜菜" #. ~ Description for sugar beet #: data/json/items/comestibles/raw_veggy.json @@ -76699,7 +76940,7 @@ msgstr "多汁的紅色番茄。從新大陸帶回後便開始在義大利流行 #: data/json/items/comestibles/raw_veggy.json msgid "plant marrow" msgid_plural "plant marrows" -msgstr[0] "" +msgstr[0] "植物嫩茎" #. ~ Description for plant marrow #: data/json/items/comestibles/raw_veggy.json @@ -76709,7 +76950,7 @@ msgstr "富含纖維與營養的植物中心, 可以生吃或煮湯。" #: data/json/items/comestibles/raw_veggy.json msgid "alien fungus chunk" msgid_plural "alien fungus chunks" -msgstr[0] "" +msgstr[0] "异界真菌块" #. ~ Description for {'str': 'alien fungus chunk'} #: data/json/items/comestibles/raw_veggy.json @@ -76734,7 +76975,7 @@ msgstr "大量看起來可以吃的野生植物, 但是大多數都苦苦的不 #: data/json/items/comestibles/seed.json msgid "zucchini" msgid_plural "zucchinis" -msgstr[0] "" +msgstr[0] "西葫芦" #. ~ Description for zucchini #: data/json/items/comestibles/raw_veggy.json @@ -76745,7 +76986,7 @@ msgstr "美味的西葫蘆。" #: data/json/items/comestibles/seed.json msgid "canola" msgid_plural "canolas" -msgstr[0] "" +msgstr[0] "油菜" #. ~ Description for canola #: data/json/items/comestibles/raw_veggy.json @@ -76810,7 +77051,7 @@ msgstr[0] "豪華三明治" #: data/json/items/comestibles/sandwich.json msgid "\"deluxe\" sandwich" msgid_plural "\"deluxe\" sandwiches" -msgstr[0] "" +msgstr[0] "特级三明治(变异肉)" #. ~ Description for {'str': 'deluxe sandwich', 'str_pl': 'deluxe sandwiches'} #: data/json/items/comestibles/sandwich.json @@ -76915,7 +77156,7 @@ msgstr[0] "人肉三明治" #, c-format msgid "mutant %s" msgid_plural "mutant %s" -msgstr[0] "" +msgstr[0] "%s(变异肉)" #. ~ Description for {'str': 'meat sandwich', 'str_pl': 'meat sandwiches'} #: data/json/items/comestibles/sandwich.json @@ -76984,7 +77225,7 @@ msgstr "美味的魚肉三明治。" #: data/json/items/comestibles/sandwich.json msgid "fish and spinach bagel" msgid_plural "fish and spinach bagels" -msgstr[0] "" +msgstr[0] "鱼配菠菜百吉饼" #. ~ Description for {'str': 'fish and spinach bagel'} #: data/json/items/comestibles/sandwich.json @@ -76994,7 +77235,7 @@ msgstr "美味的魚肉貝果加上菠菜與蛋。" #: data/json/items/comestibles/sandwich.json msgid "BLT" msgid_plural "BLTs" -msgstr[0] "" +msgstr[0] "培根生菜番茄三明治" #. ~ Description for {'str': 'BLT'} #: data/json/items/comestibles/sandwich.json @@ -77009,7 +77250,7 @@ msgstr[0] "種子" #: data/json/items/comestibles/seed.json msgid "fruit seeds" msgid_plural "fruit seeds" -msgstr[0] "" +msgstr[0] "水果种子" #: data/json/items/comestibles/seed.json msgid "mushroom spores" @@ -77386,7 +77627,7 @@ msgstr "仙人掌" #: data/json/items/comestibles/seed.json msgid "garlic clove" msgid_plural "garlic cloves" -msgstr[0] "" +msgstr[0] "蒜瓣" #. ~ Description for {'str': 'garlic clove'} #: data/json/items/comestibles/seed.json @@ -77476,7 +77717,7 @@ msgstr "一些真菌種子。" #: data/json/items/comestibles/seed.json data/mods/No_Fungi/comestibles.json msgid "Marloss seed" msgid_plural "Marloss seeds" -msgstr[0] "" +msgstr[0] "马洛斯种子" #. ~ Description for {'str': 'Marloss seed'} #: data/json/items/comestibles/seed.json @@ -77537,7 +77778,7 @@ msgstr "一些麝香草的種子。" #: data/json/items/comestibles/spice.json msgid "thyme" msgid_plural "thymes" -msgstr[0] "" +msgstr[0] "百里香" #: data/json/items/comestibles/seed.json msgid "canola seeds" @@ -77650,7 +77891,7 @@ msgstr "一些蒲公英的種子。" #: data/json/items/comestibles/seed.json msgid "burdock seeds" msgid_plural "burdock seeds" -msgstr[0] "" +msgstr[0] "牛蒡种子" #. ~ Description for {'str_sp': 'burdock seeds'} #: data/json/items/comestibles/seed.json @@ -77789,7 +78030,7 @@ msgstr "一些洋甘菊種子。" #: data/json/items/comestibles/seed.json msgid "popcorn seeds" msgid_plural "popcorn seeds" -msgstr[0] "" +msgstr[0] "爆米花玉米种子" #. ~ Description for {'str_sp': 'popcorn seeds'} #: data/json/items/comestibles/seed.json @@ -77799,7 +78040,7 @@ msgstr "一些爆米花玉米种子。" #: data/json/items/comestibles/seed.json msgid "horseradish seeds" msgid_plural "horseradish seeds" -msgstr[0] "" +msgstr[0] "辣根种子" #. ~ Description for {'str_sp': 'horseradish seeds'} #: data/json/items/comestibles/seed.json @@ -77809,7 +78050,7 @@ msgstr "一些辣根种子。" #: data/json/items/comestibles/seed.json msgid "mustard seeds" msgid_plural "mustard seeds" -msgstr[0] "" +msgstr[0] "芥末种子" #. ~ Description for {'str_sp': 'mustard seeds'} #: data/json/items/comestibles/seed.json @@ -77819,7 +78060,7 @@ msgstr "一些芥末种子。可以磨成粉末状。" #: data/json/items/comestibles/soup.json msgid "broth" msgid_plural "broths" -msgstr[0] "" +msgstr[0] "杂菜汤" #. ~ Description for broth #: data/json/items/comestibles/soup.json @@ -77829,7 +78070,7 @@ msgstr "富含營養與美味的蔬菜高湯。" #: data/json/items/comestibles/soup.json msgid "bone broth" msgid_plural "bone broths" -msgstr[0] "" +msgstr[0] "炖骨汤" #. ~ Description for bone broth #: data/json/items/comestibles/soup.json @@ -77839,7 +78080,7 @@ msgstr "精選大骨熬煮, 味美濃稠。" #: data/json/items/comestibles/soup.json msgid "vegetable soup" msgid_plural "vegetable soups" -msgstr[0] "" +msgstr[0] "蔬菜浓汤" #. ~ Description for vegetable soup #: data/json/items/comestibles/soup.json @@ -77849,13 +78090,13 @@ msgstr "富含營養與美味的多重蔬菜口味濃湯。" #: data/json/items/comestibles/soup.json msgid "meat soup" msgid_plural "meat soups" -msgstr[0] "" +msgstr[0] "肉汤" #. ~ Conditional name for meat soup when FLAG matches CANNIBALISM #: data/json/items/comestibles/soup.json msgid "sap soup" msgid_plural "sap soups" -msgstr[0] "" +msgstr[0] "浓情人肉汤" #. ~ Description for meat soup #: data/json/items/comestibles/soup.json @@ -77865,7 +78106,7 @@ msgstr "富含營養與美味的燉肉湯。" #: data/json/items/comestibles/soup.json msgid "fish soup" msgid_plural "fish soups" -msgstr[0] "" +msgstr[0] "鱼汤" #. ~ Description for fish soup #: data/json/items/comestibles/soup.json @@ -77892,7 +78133,7 @@ msgstr[0] "咖喱燉肉" #: data/json/items/comestibles/soup.json msgid "creature curry" msgid_plural "creature curries" -msgstr[0] "" +msgstr[0] "咖喱(变异肉)" #. ~ Description for {'str': 'curry with meat', 'str_pl': 'curries with meat'} #: data/json/items/comestibles/soup.json @@ -77902,13 +78143,13 @@ msgstr "充滿了辣椒丁的咖喱燉肉、辛辣又好吃。" #: data/json/items/comestibles/soup.json msgid "woods soup" msgid_plural "woods soups" -msgstr[0] "" +msgstr[0] "森林杂烩汤" #. ~ Conditional name for woods soup when COMPONENT_ID matches mutant #: data/json/items/comestibles/soup.json msgid "Mirkwood soup" msgid_plural "Mirkwood soups" -msgstr[0] "" +msgstr[0] "森林杂烩汤(变异肉)" #. ~ Description for woods soup #: data/json/items/comestibles/soup.json @@ -77918,7 +78159,7 @@ msgstr "美味營養的濃湯, 純天然素材熬煮。" #: data/json/items/comestibles/soup.json msgid "chicken noodle soup" msgid_plural "chicken noodle soups" -msgstr[0] "" +msgstr[0] "鸡汤面" #. ~ Description for chicken noodle soup #: data/json/items/comestibles/soup.json @@ -77930,7 +78171,7 @@ msgstr "雞丁和麵條泡在鹹味肉湯裡。傳言可以治感冒。" #: data/json/items/comestibles/soup.json msgid "mushroom soup" msgid_plural "mushroom soups" -msgstr[0] "" +msgstr[0] "蘑菇汤" #. ~ Description for mushroom soup #: data/json/items/comestibles/soup.json @@ -77940,7 +78181,7 @@ msgstr "糊狀, 灰色半流質的蘑菇湯。" #: data/json/items/comestibles/soup.json msgid "tomato soup" msgid_plural "tomato soups" -msgstr[0] "" +msgstr[0] "番茄汤" #. ~ Description for tomato soup #: data/json/items/comestibles/soup.json @@ -77962,7 +78203,7 @@ msgstr "罐裝雞湯, 裡面還有雞丁和小麵糰。味道還可以。" #: data/json/items/comestibles/soup.json msgid "cullen skink" msgid_plural "cullen skinks" -msgstr[0] "" +msgstr[0] "卡伦浓汤" #. ~ Description for cullen skink #: data/json/items/comestibles/soup.json @@ -78103,7 +78344,7 @@ msgstr "一根麝香草。聞起來很好吃。" #: data/json/items/comestibles/spice.json msgid "mustard powder" msgid_plural "mustard powder" -msgstr[0] "" +msgstr[0] "芥末粉" #. ~ Description for {'str_sp': 'mustard powder'} #: data/json/items/comestibles/spice.json @@ -78113,7 +78354,7 @@ msgstr "一种有香气的黄色粉末。还不能食用。" #: data/json/items/comestibles/veggy_dishes.json msgid "cooked cattail stalk" msgid_plural "cooked cattail stalks" -msgstr[0] "" +msgstr[0] "煮香蒲秆" #. ~ Description for {'str': 'cooked cattail stalk'} #: data/json/items/comestibles/veggy_dishes.json @@ -78186,7 +78427,7 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "cooked burdock greens" msgid_plural "cooked burdock greens" -msgstr[0] "" +msgstr[0] "煮牛蒡叶" #. ~ Description for {'str_sp': 'cooked burdock greens'} #: data/json/items/comestibles/veggy_dishes.json @@ -78196,7 +78437,7 @@ msgstr "一份煮熟的牛蒡叶片,美味且营养丰富,有助于健康。 #: data/json/items/comestibles/veggy_dishes.json msgid "fried burdocks" msgid_plural "fried burdocks" -msgstr[0] "" +msgstr[0] "面拖牛蒡" #. ~ Description for {'str_sp': 'fried burdocks'} #: data/json/items/comestibles/veggy_dishes.json @@ -78210,7 +78451,7 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "fried dandelions and burdocks" msgid_plural "fried dandelions burdocks" -msgstr[0] "" +msgstr[0] "面拖蒲公英配牛蒡" #. ~ Description for {'str': 'fried dandelions and burdocks', 'str_pl': 'fried #. dandelions burdocks'} @@ -78225,7 +78466,7 @@ msgstr "" #: data/json/items/comestibles/veggy_dishes.json msgid "cooked plant marrow" msgid_plural "cooked plant marrows" -msgstr[0] "" +msgstr[0] "炖植物嫩茎" #. ~ Description for cooked plant marrow #: data/json/items/comestibles/veggy_dishes.json @@ -78245,7 +78486,7 @@ msgstr "由可食野菜燉煮, 具有特殊風味。" #: data/json/items/comestibles/veggy_dishes.json msgid "vegetable aspic" msgid_plural "vegetable aspics" -msgstr[0] "" +msgstr[0] "菜冻" #. ~ Description for vegetable aspic #: data/json/items/comestibles/veggy_dishes.json @@ -78272,7 +78513,7 @@ msgstr "罐頭裝的浸漬玉米。吃吧!" #: data/json/items/comestibles/veggy_dishes.json msgid "hominy" msgid_plural "hominy" -msgstr[0] "" +msgstr[0] "玉米糁" #. ~ Description for {'str_sp': 'hominy'} #: data/json/items/comestibles/veggy_dishes.json @@ -78284,7 +78525,7 @@ msgstr "一些用碱性溶液煮熟并漂洗干净的玉米碎粒,使其更适 #: data/json/items/comestibles/veggy_dishes.json msgid "cornmeal" msgid_plural "cornmeal" -msgstr[0] "" +msgstr[0] "玉米面" #. ~ Description for {'str_sp': 'cornmeal'} #: data/json/items/comestibles/veggy_dishes.json @@ -78392,7 +78633,7 @@ msgstr "一個美味的熟馬鈴薯。有醬料可以加嗎?" #: data/json/items/comestibles/veggy_dishes.json msgid "mashed pumpkin" msgid_plural "mashed pumpkins" -msgstr[0] "" +msgstr[0] "南瓜泥" #. ~ Description for mashed pumpkin #: data/json/items/comestibles/veggy_dishes.json @@ -78403,7 +78644,7 @@ msgstr "這是一種簡單的菜, 將煮過的南瓜肉搗碎。" #: data/json/items/comestibles/veggy_dishes.json msgid "vegetable pie" msgid_plural "vegetable pies" -msgstr[0] "" +msgstr[0] "鲜蔬派" #. ~ Description for vegetable pie #: data/json/items/comestibles/veggy_dishes.json @@ -78413,7 +78654,7 @@ msgstr "一種有美味蔬菜餡的烤餡餅。" #: data/json/items/comestibles/veggy_dishes.json msgid "vegetable pizza" msgid_plural "vegetable pizzas" -msgstr[0] "" +msgstr[0] "蔬菜披萨" #. ~ Description for vegetable pizza #: data/json/items/comestibles/veggy_dishes.json @@ -78425,7 +78666,7 @@ msgstr "一個素食的披薩, 加入美味的番茄沙司與蓬鬆的餅皮。 #: data/json/items/comestibles/veggy_dishes.json msgid "pesto" msgid_plural "pesto" -msgstr[0] "" +msgstr[0] "香蒜沙司" #. ~ Description for {'str_sp': 'pesto'} #: data/json/items/comestibles/veggy_dishes.json @@ -78447,7 +78688,7 @@ msgstr "這些糊狀的蔬菜已經用水煮熟並且裝罐。你最好在它從 #: data/json/items/comestibles/veggy_dishes.json msgid "salted veggy chunk" msgid_plural "salted veggy chunks" -msgstr[0] "" +msgstr[0] "腌菜块" #. ~ Description for salted veggy chunk #: data/json/items/comestibles/veggy_dishes.json @@ -78469,7 +78710,7 @@ msgstr "義大利麵, 上面灑滿了美味香蒜, 太迷人了!" #: data/json/items/comestibles/veggy_dishes.json msgid "pickle" msgid_plural "pickles" -msgstr[0] "" +msgstr[0] "腌瓜" #. ~ Description for pickle #: data/json/items/comestibles/veggy_dishes.json @@ -78504,7 +78745,7 @@ msgstr "這是一罐又香又脆的醃漬蔬菜。美味又營養。" #: data/json/items/comestibles/veggy_dishes.json msgid "dehydrated vegetable" msgid_plural "dehydrated vegetables" -msgstr[0] "" +msgstr[0] "脱水蔬菜" #. ~ Description for dehydrated vegetable #: data/json/items/comestibles/veggy_dishes.json @@ -78516,7 +78757,7 @@ msgstr "脫水過的蔬菜。在合適的儲存下, 這個乾燥食物能夠保 #: data/json/items/comestibles/veggy_dishes.json msgid "rehydrated vegetable" msgid_plural "rehydrated vegetables" -msgstr[0] "" +msgstr[0] "水发蔬菜" #. ~ Description for rehydrated vegetable #: data/json/items/comestibles/veggy_dishes.json @@ -78528,7 +78769,7 @@ msgstr "沖調過的脫水蔬菜, 重新加了水之後讓這東西變得更好 #: data/json/items/comestibles/veggy_dishes.json msgid "vegetable salad" msgid_plural "vegetable salads" -msgstr[0] "" +msgstr[0] "蔬菜沙拉" #. ~ Description for vegetable salad #: data/json/items/comestibles/veggy_dishes.json @@ -78538,7 +78779,7 @@ msgstr "各種蔬菜製作的沙拉。" #: data/json/items/comestibles/veggy_dishes.json msgid "dried salad" msgid_plural "dried salads" -msgstr[0] "" +msgstr[0] "方便沙拉" #. ~ Description for dried salad #: data/json/items/comestibles/veggy_dishes.json @@ -78550,7 +78791,7 @@ msgstr "裝在盒子裡的乾燥沙拉, 配有美乃滋醬與番茄醬包。加 #: data/json/items/comestibles/veggy_dishes.json msgid "insta-salad" msgid_plural "insta-salads" -msgstr[0] "" +msgstr[0] "即食沙拉" #. ~ Description for insta-salad #: data/json/items/comestibles/veggy_dishes.json @@ -78562,7 +78803,7 @@ msgstr "加水後的乾燥沙拉, 不好吃, 但仍然是一個像樣的替代 #: data/json/items/comestibles/veggy_dishes.json msgid "baked dahlia root" msgid_plural "baked dahlia roots" -msgstr[0] "" +msgstr[0] "烤大丽花根" #. ~ Description for {'str': 'baked dahlia root'} #: data/json/items/comestibles/veggy_dishes.json @@ -78574,7 +78815,7 @@ msgstr "烤过的大丽花根已经分解了其中的部分淀粉,这使它变 #: data/json/items/comestibles/veggy_dishes.json msgid "roasted salsify" msgid_plural "roasted salsifies" -msgstr[0] "" +msgstr[0] "烤蒜叶婆罗门参" #. ~ Description for {'str': 'roasted salsify', 'str_pl': 'roasted salsifies'} #: data/json/items/comestibles/veggy_dishes.json @@ -78620,7 +78861,7 @@ msgstr "以健康綠色蔬菜包起可口的壽司飯與碎菜做成的細捲壽 #: data/json/items/comestibles/veggy_dishes.json msgid "dehydrated alien fungus chunk" msgid_plural "dehydrated alien fungus chunks" -msgstr[0] "" +msgstr[0] "脱水异界真菌块" #. ~ Description for dehydrated alien fungus chunk #: data/json/items/comestibles/veggy_dishes.json @@ -78644,7 +78885,7 @@ msgstr "這種脆脆、酸酸的餡料由萵苣或是捲心菜製成, 配上熱 #: data/json/items/comestibles/veggy_dishes.json msgid "nopalito" msgid_plural "nopalitos" -msgstr[0] "" +msgstr[0] "仙人掌嫩茎" #. ~ Description for nopalito #: data/json/items/comestibles/veggy_dishes.json @@ -78674,7 +78915,7 @@ msgstr "蕨類嫩芽用脂肪嫩煎過。鮮嫩可口。" #: data/json/items/comestibles/wheat.json msgid "wheat cereal" msgid_plural "wheat cereals" -msgstr[0] "" +msgstr[0] "早餐燕麦" #. ~ Description for wheat cereal #: data/json/items/comestibles/wheat.json @@ -78767,7 +79008,7 @@ msgstr "這個白色的營養強化麵粉在烘焙時很有用。" #: data/json/items/comestibles/wheat.json msgid "oatmeal" msgid_plural "oatmeal" -msgstr[0] "" +msgstr[0] "生麦片" #. ~ Description for {'str_sp': 'oatmeal'} #: data/json/items/comestibles/wheat.json @@ -78784,7 +79025,7 @@ msgstr "生燕麥。" #: data/json/items/comestibles/wheat.json msgid "cooked oatmeal" msgid_plural "cooked oatmeal" -msgstr[0] "" +msgstr[0] "煮麦片" #. ~ Description for {'str_sp': 'cooked oatmeal'} #: data/json/items/comestibles/wheat.json @@ -78796,7 +79037,7 @@ msgstr "營養又飽足的新英格蘭經典餐點, 受到開墾者與企業領 #: data/json/items/comestibles/wheat.json msgid "deluxe cooked oatmeal" msgid_plural "deluxe cooked oatmeal" -msgstr[0] "" +msgstr[0] "美味煮麦片" #. ~ Description for {'str_sp': 'deluxe cooked oatmeal'} #: data/json/items/comestibles/wheat.json @@ -78808,7 +79049,7 @@ msgstr "營養又飽足的新英格蘭經典餐點, 還增加了豪華口味的 #: data/json/items/comestibles/wheat.json msgid "pancake" msgid_plural "pancakes" -msgstr[0] "" +msgstr[0] "馅饼" #. ~ Description for {'str': 'pancake'} #: data/json/items/comestibles/wheat.json @@ -78818,7 +79059,7 @@ msgstr "蓬鬆可口的煎餅淋上了純正的楓糖漿。" #: data/json/items/comestibles/wheat.json msgid "fruit pancake" msgid_plural "fruit pancakes" -msgstr[0] "" +msgstr[0] "水果馅饼" #. ~ Description for {'str': 'fruit pancake'} #: data/json/items/comestibles/wheat.json @@ -78840,7 +79081,7 @@ msgstr "切片的麵包浸過牛奶和雞蛋的混合物之後再炸。" #: data/json/items/comestibles/wheat.json msgid "waffle" msgid_plural "waffles" -msgstr[0] "" +msgstr[0] "华夫饼" #. ~ Description for waffle #: data/json/items/comestibles/wheat.json @@ -78852,7 +79093,7 @@ msgstr "嘿! 該吃鬆餅了, 鬆餅時間到了。你要吃吃我做的鬆餅 #: data/json/items/comestibles/wheat.json msgid "fruit waffle" msgid_plural "fruit waffles" -msgstr[0] "" +msgstr[0] "水果华夫饼" #. ~ Description for fruit waffle #: data/json/items/comestibles/wheat.json @@ -78863,9 +79104,10 @@ msgstr "蓬鬆可口的鬆餅淋上了純正的楓糖漿, 成為了甜口味, #: data/json/items/comestibles/wheat.json #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json +#: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "cracker" msgid_plural "crackers" -msgstr[0] "" +msgstr[0] "薄脆饼干" #. ~ Description for cracker #: data/json/items/comestibles/wheat.json @@ -78875,7 +79117,7 @@ msgstr "乾又鹹, 吃這些餅乾會讓你口渴。" #: data/json/items/comestibles/wheat.json msgid "fruit pie" msgid_plural "fruit pies" -msgstr[0] "" +msgstr[0] "水果派" #. ~ Description for fruit pie #: data/json/items/comestibles/wheat.json @@ -78885,7 +79127,7 @@ msgstr "一個加入許多甜美水果的美味烘焙派。" #: data/json/items/comestibles/wheat.json msgid "cheese pizza" msgid_plural "cheese pizzas" -msgstr[0] "" +msgstr[0] "奶酪披萨" #. ~ Description for cheese pizza #: data/json/items/comestibles/wheat.json @@ -78895,7 +79137,7 @@ msgstr "一個美味的披薩, 上面鋪有熔化的起司。" #: data/json/items/comestibles/wheat.json msgid "granola" msgid_plural "granola" -msgstr[0] "" +msgstr[0] "格兰诺拉燕麦卷" #. ~ Description for {'str_sp': 'granola'} #: data/json/items/comestibles/wheat.json @@ -78907,7 +79149,7 @@ msgstr "混合了蜂蜜等成分的燕麥片, 營養豐富又香脆可口。" #: data/json/items/comestibles/wheat.json msgid "maple pie" msgid_plural "maple pies" -msgstr[0] "" +msgstr[0] "枫糖馅饼" #. ~ Description for maple pie #: data/json/items/comestibles/wheat.json @@ -78927,7 +79169,7 @@ msgstr "傳說中的人類最偉大發明。能夠生吃。" #: data/json/items/comestibles/wheat.json msgid "cloutie dumpling" msgid_plural "cloutie dumplings" -msgstr[0] "" +msgstr[0] "魔鬼布丁" #. ~ Description for cloutie dumpling #: data/json/items/comestibles/wheat.json @@ -78939,7 +79181,7 @@ msgstr "傳統的蘇格蘭美食, 一個有乾果餡的小蛋糕, 既甜美又 #: data/json/items/comestibles/wheat.json msgid "brioche" msgid_plural "brioches" -msgstr[0] "" +msgstr[0] "法式奶油面包卷" #. ~ Description for brioche #: data/json/items/comestibles/wheat.json @@ -78949,7 +79191,7 @@ msgstr "一種法式軟麵包。很適合搭配一杯茶當做星期天的早餐 #: data/json/items/comestibles/wheat.json msgid "sponge cake" msgid_plural "sponge cakes" -msgstr[0] "" +msgstr[0] "松蛋糕" #. ~ Description for sponge cake #: data/json/items/comestibles/wheat.json @@ -78959,7 +79201,7 @@ msgstr "無產階級的樸素而蓬鬆蛋糕。" #: data/json/items/comestibles/wheat.json msgid "space cake" msgid_plural "space cakes" -msgstr[0] "" +msgstr[0] "太空蛋糕" #. ~ Description for space cake #: data/json/items/comestibles/wheat.json @@ -78969,7 +79211,7 @@ msgstr "這蛋糕可以帶你體驗一段\"旅程\"。" #: data/json/items/comestibles/wheat.json msgid "brownie" msgid_plural "brownies" -msgstr[0] "" +msgstr[0] "布朗尼蛋糕" #. ~ Description for brownie #: data/json/items/comestibles/wheat.json @@ -78979,7 +79221,7 @@ msgstr "加入大量巧克力布朗尼,就像奶奶烤的一樣。" #: data/json/items/comestibles/wheat.json msgid "'special' brownie" msgid_plural "'special' brownies" -msgstr[0] "" +msgstr[0] "特制布朗尼蛋糕" #. ~ Description for {'str': "'special' brownie"} #: data/json/items/comestibles/wheat.json @@ -78997,20 +79239,20 @@ msgstr[0] "屍體" #: data/json/items/corpses/corpses.json msgid "carcass" msgid_plural "carcasses" -msgstr[0] "" +msgstr[0] "胴体" #. ~ Conditional name for {'str': 'corpse'} when FLAG matches SKINNED #: data/json/items/corpses/corpses.json #, c-format msgid "skinned %s" msgid_plural "skinned %s" -msgstr[0] "" +msgstr[0] "%s(已剥皮)" #. ~ Conditional name for {'str': 'corpse'} when FLAG matches QUARTERED #: data/json/items/corpses/corpses.json msgid "carcass quarter" msgid_plural "carcass quarters" -msgstr[0] "" +msgstr[0] "四分体" #. ~ Description for {'str': 'corpse'} #: data/json/items/corpses/corpses.json @@ -79587,7 +79829,7 @@ msgstr "一台未激活的清洁机器人。使用该物品以将它放置在地 #: data/json/items/corpses/inactive_bots.json msgid "inactive hauler bot" msgid_plural "inactive hauler bots" -msgstr[0] "" +msgstr[0] "运输机器人(关)" #. ~ Use action friendly_msg for {'str': 'inactive hauler bot'}. #: data/json/items/corpses/inactive_bots.json @@ -79740,7 +79982,7 @@ msgstr "" #: data/json/items/corpses/inactive_bots.json msgid "inactive dispatch" msgid_plural "inactive dispatches" -msgstr[0] "" +msgstr[0] "派遣者(关)" #. ~ Use action friendly_msg for {'str': 'inactive dispatch', 'str_pl': #. 'inactive dispatches'}. @@ -79770,7 +80012,7 @@ msgstr "" #: data/json/items/corpses/inactive_bots.json msgid "inactive military dispatch" msgid_plural "inactive military dispatches" -msgstr[0] "" +msgstr[0] "军用派遣者(关)" #. ~ Use action hostile_msg for {'str': 'inactive military dispatch', #. 'str_pl': 'inactive military dispatches'}. @@ -79793,7 +80035,7 @@ msgstr "" #: data/json/items/corpses/inactive_bots.json msgid "inactive autonomous light turret" msgid_plural "inactive autonomous light turrets" -msgstr[0] "" +msgstr[0] "轻型自动炮塔(关)" #. ~ Description for {'str': 'inactive autonomous light turret'} #: data/json/items/corpses/inactive_bots.json @@ -79810,7 +80052,7 @@ msgstr "" #: data/json/items/corpses/inactive_bots.json msgid "inactive autonomous medium milspec turret" msgid_plural "inactive autonomous medium milspec turrets" -msgstr[0] "" +msgstr[0] "中型军用自动炮塔(关)" #. ~ Description for {'str': 'inactive autonomous medium milspec turret'} #: data/json/items/corpses/inactive_bots.json @@ -79828,7 +80070,7 @@ msgstr "" #: data/json/items/corpses/inactive_bots.json msgid "inactive autonomous longrange milspec turret" msgid_plural "inactive autonomous longrange milspec turrets" -msgstr[0] "" +msgstr[0] "长程军用自动炮塔(关)" #. ~ Description for {'str': 'inactive autonomous longrange milspec turret'} #: data/json/items/corpses/inactive_bots.json @@ -79877,7 +80119,7 @@ msgstr[0] ".50 彈鏈帶" #: data/json/items/generic/bathroom_house.json msgid "generic grooming" msgid_plural "generic groomings" -msgstr[0] "" +msgstr[0] "虚拟毛刷" #. ~ Description for {'str': 'generic grooming'} #. ~ Description for {'str': 'generic silverware'} @@ -79895,7 +80137,7 @@ msgstr "通用物品模板" #: data/json/items/generic/bathroom_house.json msgid "shaving razor" msgid_plural "shaving razors" -msgstr[0] "" +msgstr[0] "剃须刀" #. ~ Description for {'str': 'shaving razor'} #: data/json/items/generic/bathroom_house.json @@ -79907,7 +80149,7 @@ msgstr "一把剃须刀,刀片安装在一个舒适的手柄上。用剃须刀 #: data/json/items/generic/bathroom_house.json msgid "hairbrush" msgid_plural "hairbrushes" -msgstr[0] "" +msgstr[0] "发梳" #. ~ Description for {'str': 'hairbrush', 'str_pl': 'hairbrushes'} #: data/json/items/generic/bathroom_house.json @@ -79936,7 +80178,7 @@ msgstr "一把十分俗气的儿童发梳。手柄上的卡通鲸鱼似乎很友 #: data/json/items/generic/bathroom_house.json msgid "dental floss" msgid_plural "rolls of dental floss" -msgstr[0] "" +msgstr[0] "牙线" #. ~ Description for {'str': 'dental floss', 'str_pl': 'rolls of dental #. floss'} @@ -79983,7 +80225,7 @@ msgstr "一把带有折叠铰链的梳子,想当油头滑面的时髦少年就 #: data/json/items/generic/bathroom_house.json msgid "hair dryer" msgid_plural "hair dryers" -msgstr[0] "" +msgstr[0] "吹风机" #. ~ Description for {'str': 'hair dryer'} #: data/json/items/generic/bathroom_house.json @@ -79995,7 +80237,7 @@ msgstr "一个通过加热线圈及推动空气使你的头发变干的电动工 #: data/json/items/generic/bathroom_house.json msgid "curling iron" msgid_plural "curling irons" -msgstr[0] "" +msgstr[0] "卷发钳" #. ~ Description for {'str': 'curling iron'} #: data/json/items/generic/bathroom_house.json @@ -80093,7 +80335,7 @@ msgstr "一個空的 .22 LR 子彈殼。它們無法再次手工裝填。" #: data/json/items/generic/casing.json msgid "unused .22 casing" msgid_plural "unused .22 casings" -msgstr[0] "" +msgstr[0] ".22 弹壳(未使用)" #. ~ Description for {'str': 'unused .22 casing'} #: data/json/items/generic/casing.json @@ -80203,7 +80445,7 @@ msgstr "10mm Auto弹的空弹壳。" #: data/json/items/generic/casing.json msgid "40x46mm M212 casing" msgid_plural "40x46mm M212 casings" -msgstr[0] "" +msgstr[0] "40x46mm M212 榴弹弹壳" #. ~ Description for {'str': '40x46mm M212 casing'} #: data/json/items/generic/casing.json @@ -80217,7 +80459,7 @@ msgstr "" #: data/json/items/generic/casing.json msgid "40x46mm M118 casing" msgid_plural "40x46mm M118 casings" -msgstr[0] "" +msgstr[0] "40x46mm M118 榴弹弹壳" #. ~ Description for {'str': '40x46mm M118 casing'} #: data/json/items/generic/casing.json @@ -80229,7 +80471,7 @@ msgstr "M433 HEDP弹药使用的40mm子弹中的一个大罐。它可以被用 #: data/json/items/generic/casing.json msgid "40x46mm M199 casing" msgid_plural "40x46mm M199 casings" -msgstr[0] "" +msgstr[0] "40x46mm M199 榴弹弹壳" #. ~ Description for {'str': '40x46mm M199 casing'} #: data/json/items/generic/casing.json @@ -80241,7 +80483,7 @@ msgstr "M576霰弹枪使用的40毫米子弹中的弹壳。它可以重复使用 #: data/json/items/generic/casing.json msgid "40x46mm M195 casing" msgid_plural "40x46mm M195 casings" -msgstr[0] "" +msgstr[0] "40x46mm M195 榴弹弹壳" #. ~ Description for {'str': '40x46mm M195 casing'} #: data/json/items/generic/casing.json @@ -80255,7 +80497,7 @@ msgstr "" #: data/json/items/generic/casing.json msgid "40x53mm M169 casing" msgid_plural "40x53mm M169 casings" -msgstr[0] "" +msgstr[0] "40x53mm M169 榴弹弹壳" #. ~ Description for {'str': '40x53mm M169 casing'} #: data/json/items/generic/casing.json @@ -80481,7 +80723,7 @@ msgstr "一個空的 .380 ACP 子彈殼。" #: data/json/items/generic/casing.json msgid "152mm ATGM tube" msgid_plural "152mm ATGM tubes" -msgstr[0] "" +msgstr[0] "152mm反坦克导弹发射管" #. ~ Description for {'str': '152mm ATGM tube'} #: data/json/items/generic/casing.json @@ -80568,7 +80810,7 @@ msgstr "" #: data/json/items/generic/currency.json msgid "chit" msgid_plural "chits" -msgstr[0] "" +msgstr[0] "欠条" #. ~ Description for {'str': 'chit'} #: data/json/items/generic/currency.json @@ -80578,7 +80820,7 @@ msgstr "这是某个人签的欠条。" #: data/json/items/generic/currency.json msgid "icon" msgid_plural "icons" -msgstr[0] "" +msgstr[0] "圣像" #. ~ Description for {'str': 'icon'} #: data/json/items/generic/currency.json @@ -80591,7 +80833,7 @@ msgstr "一张画着图的小卡片,大小和一张ID卡差不多,上面的 #: data/json/items/generic/dining_kitchen.json msgid "generic silverware" msgid_plural "generic silverwares" -msgstr[0] "" +msgstr[0] "一般银器" #: data/json/items/generic/dining_kitchen.json msgid "generic utensil" @@ -80601,12 +80843,12 @@ msgstr[0] "通用器具" #: data/json/items/generic/dining_kitchen.json msgid "generic dish" msgid_plural "generic dishes" -msgstr[0] "" +msgstr[0] "普通菜肴" #: data/json/items/generic/dining_kitchen.json msgid "generic cook pot" msgid_plural "generic cook pots" -msgstr[0] "" +msgstr[0] "一般烹饪锅" #: data/json/items/generic/dining_kitchen.json msgid "ceramic plate" @@ -80806,7 +81048,7 @@ msgstr "一个带有方便密封盖的塑料碗,可以储存750毫升液体。 #: data/json/items/generic/dining_kitchen.json msgid "kiddie bowl" msgid_plural "kiddie bowls" -msgstr[0] "" +msgstr[0] "儿童碗" #. ~ Description for {'str': 'kiddie bowl'} #: data/json/items/generic/dining_kitchen.json @@ -80847,7 +81089,7 @@ msgstr "这个碗上有着可爱的农场动物做装饰。" #: data/json/items/generic/dining_kitchen.json msgid "sippy cup" msgid_plural "sippy cups" -msgstr[0] "" +msgstr[0] "吸管杯" #. ~ Description for {'str': 'sippy cup'} #: data/json/items/generic/dining_kitchen.json @@ -81029,7 +81271,7 @@ msgstr "用于烧开水的炉灶水壶。" #: data/json/items/generic/music.json msgid "XLR cable" msgid_plural "XLR cables" -msgstr[0] "" +msgstr[0] "卡农线" #. ~ Description for {'str': 'XLR cable'} #: data/json/items/generic/music.json @@ -81041,7 +81283,7 @@ msgstr "一根用于传输音频信号的平衡电缆。连接器上有三根芯 #: data/json/items/generic/music.json msgid "speaker cable" msgid_plural "speaker cables" -msgstr[0] "" +msgstr[0] "喇叭线" #. ~ Description for {'str': 'speaker cable'} #: data/json/items/generic/music.json @@ -81053,7 +81295,7 @@ msgstr "一根能将一个扬声器连接到电源插头,或将一个扬声器 #: data/json/items/generic/music.json msgid "instrument cable" msgid_plural "instrument cables" -msgstr[0] "" +msgstr[0] "乐器线" #. ~ Description for {'str': 'instrument cable'} #: data/json/items/generic/music.json @@ -81066,7 +81308,7 @@ msgstr "一根通常用于将吉他连接到功率放大器的乐器线,属于 #: data/json/items/generic/music.json msgid "headphones" msgid_plural "headphones" -msgstr[0] "" +msgstr[0] "耳机" #. ~ Description for {'str_sp': 'headphones'} #: data/json/items/generic/music.json @@ -81079,7 +81321,7 @@ msgstr "一个常见的头戴式耳机。这个耳机是个名牌产品,音质 #: data/json/items/generic/music.json msgid "XLR microphone" msgid_plural "XLR microphones" -msgstr[0] "" +msgstr[0] "卡农麦克风" #. ~ Description for {'str': 'XLR microphone'} #: data/json/items/generic/music.json @@ -81091,7 +81333,7 @@ msgstr "一个常见的用来录音或放大声音的麦克风。有一个夹子 #: data/json/items/generic/music.json msgid "microphone stand" msgid_plural "microphone stands" -msgstr[0] "" +msgstr[0] "麦克风架" #. ~ Description for {'str': 'microphone stand'} #: data/json/items/generic/music.json @@ -81104,7 +81346,7 @@ msgstr "一个的伸缩式臂架,由钢制成,被漆成黑色。完全伸展 #: data/json/items/generic/music.json msgid "guitar stand" msgid_plural "guitar stands" -msgstr[0] "" +msgstr[0] "吉他架" #. ~ Description for {'str': 'guitar stand'} #: data/json/items/generic/music.json @@ -81116,7 +81358,7 @@ msgstr "一个三条腿的形状奇特的小型钢制五金件。当放在地上 #: data/json/items/generic/music.json msgid "mixer" msgid_plural "mixers" -msgstr[0] "" +msgstr[0] "混音器" #. ~ Description for {'str': 'mixer'} #: data/json/items/generic/music.json @@ -81259,7 +81501,7 @@ msgstr "一种简易铸铁机械叶轮泵。单独它自己并没有什么用。 #: data/json/items/generic/storage.json msgid "clothes hanger" msgid_plural "clothes hangers" -msgstr[0] "" +msgstr[0] "衣架" #. ~ Description for {'str': 'clothes hanger'} #: data/json/items/generic/storage.json @@ -81270,7 +81512,7 @@ msgstr "一个带金属钩的塑料衣架,能在挂衣杆上挂衣服。" #: data/json/items/generic/string.json msgid "short cordage piece" msgid_plural "short cordage pieces" -msgstr[0] "" +msgstr[0] "短纤维线" #. ~ Description for {'str': 'short cordage piece'} #: data/json/items/generic/string.json @@ -81282,7 +81524,7 @@ msgstr "一根六英寸(约15厘米)长的天然纤维。可用于某些制 #: data/json/items/generic/string.json msgid "long cordage piece" msgid_plural "long cordage pieces" -msgstr[0] "" +msgstr[0] "长纤维线" #. ~ Description for {'str': 'long cordage piece'} #: data/json/items/generic/string.json @@ -81294,7 +81536,7 @@ msgstr "一根三英尺(约90厘米)长的天然纤维。可用于某些制 #: data/json/items/generic/string.json msgid "short string" msgid_plural "short strings" -msgstr[0] "" +msgstr[0] "短线" #. ~ Description for {'str': 'short string'} #: data/json/items/generic/string.json @@ -81337,7 +81579,7 @@ msgstr "一段三十英尺(约9米)长的绳索。有效保护你从高处 #: data/json/items/generic/string.json msgid "short vine" msgid_plural "short vines" -msgstr[0] "" +msgstr[0] "短藤" #. ~ Description for {'str': 'short vine'} #: data/json/items/generic/string.json @@ -81348,7 +81590,7 @@ msgstr "一段六英尺(约180厘米)长的坚固藤蔓。因为太短所以 #: data/json/items/generic/string.json msgid "long vine" msgid_plural "long vines" -msgstr[0] "" +msgstr[0] "长藤" #. ~ Description for {'str': 'long vine'} #: data/json/items/generic/string.json @@ -81360,7 +81602,7 @@ msgstr "一段三十英尺(约9米)长的藤蔓。完全可以替代绳子 #: data/json/items/generic/string.json msgid "short cordage rope" msgid_plural "short cordage ropes" -msgstr[0] "" +msgstr[0] "短纤维绳" #. ~ Description for {'str': 'short cordage rope'} #: data/json/items/generic/string.json @@ -81373,7 +81615,7 @@ msgstr "一根六英尺(约180厘米)长的绳索,采用天然纤维编织 #: data/json/items/generic/string.json msgid "long cordage rope" msgid_plural "long cordage ropes" -msgstr[0] "" +msgstr[0] "长纤维绳" #. ~ Description for {'str': 'long cordage rope'} #: data/json/items/generic/string.json @@ -81399,7 +81641,7 @@ msgstr "一段合成纤维编织成的扁平带子,通常用于将乘客安全 #: data/json/items/generic/string.json msgid "fibrous stalk" msgid_plural "fibrous stalks" -msgstr[0] "" +msgstr[0] "纤维茎秆" #. ~ Description for fibrous stalk #: data/json/items/generic/string.json @@ -81421,7 +81663,7 @@ msgstr "一個小孩玩的會說話玩偶。還好還有電, 你能夠從裡面 #: data/json/items/gun/12mm.json msgid "H&K G80 railgun" msgid_plural "H&K G80 railguns" -msgstr[0] "" +msgstr[0] "H&K G80 轨道枪" #: data/json/items/gun/12mm.json msgid "" @@ -81637,7 +81879,7 @@ msgstr "这把普及的步枪是 M16 步枪系列的前身,它重量轻,准 #: data/json/items/gun/223.json msgid "AR pistol" msgid_plural "AR pistols" -msgstr[0] "" +msgstr[0] "AR 手枪" #: data/json/items/gun/223.json msgid "" @@ -81648,7 +81890,7 @@ msgstr "一把采用经典 AR-15 步枪设计,结构紧凑,使用7.5英寸 #: data/json/items/gun/223.json msgid "MAS 223" msgid_plural "MAS 223" -msgstr[0] "" +msgstr[0] "MAS 223 步枪" #: data/json/items/gun/223.json msgid "" @@ -81759,7 +82001,7 @@ msgstr "2 連發" #: data/json/items/gun/223.json msgid "OA-93" msgid_plural "OA-93s" -msgstr[0] "" +msgstr[0] "OA-93 手枪" #: data/json/items/gun/223.json msgid "" @@ -81839,7 +82081,7 @@ msgstr "一把设计精良的自制卡宾枪,已经锯短枪管。支持原始 #: data/json/items/gun/270win.json msgid "Remington 700 .270 Win" msgid_plural "Remington 700 .270 Win" -msgstr[0] "" +msgstr[0] "雷明顿 700 步枪(.270 温彻斯特弹)" #: data/json/items/gun/270win.json msgid "" @@ -81949,7 +82191,7 @@ msgstr "" #: data/json/items/gun/3006.json msgid "Remington 700 .30-06" msgid_plural "Remington 700 .30-06" -msgstr[0] "" +msgstr[0] "雷明顿 700 步枪(.30-06 弹)" #: data/json/items/gun/3006.json msgid "" @@ -82091,7 +82333,7 @@ msgstr "" #: data/json/items/gun/308.json msgid "handmade heavy carbine" msgid_plural "handmade heavy carbines" -msgstr[0] "" +msgstr[0] "自制重型卡宾枪" #: data/json/items/gun/308.json msgid "" @@ -82252,7 +82494,7 @@ msgstr "一把全尺寸的格洛克手枪,使用 .357 西格弹。它与格洛 #: data/json/items/gun/357sig.json msgid "SIG P320 Compact" msgid_plural "SIG P320 Compacts" -msgstr[0] "" +msgstr[0] "西格&绍尔 P320 紧凑型手枪" #: data/json/items/gun/357sig.json msgid "" @@ -82289,7 +82531,7 @@ msgstr "" #: data/json/items/gun/38.json msgid "COP .357 Derringer" msgid_plural "COP .357 Derringers" -msgstr[0] "" +msgstr[0] "COP .357德林加手枪" #: data/json/items/gun/38.json msgid "" @@ -82303,7 +82545,7 @@ msgstr "" #: data/json/items/gun/38.json msgid "S&W Model 10" msgid_plural "S&W Model 10" -msgstr[0] "" +msgstr[0] "S&W Model 10 左轮手枪" #: data/json/items/gun/38.json msgid "" @@ -82315,7 +82557,7 @@ msgstr "一把六发左轮手枪,最早于1899年生产,被誉为20世纪最 #: data/json/items/gun/38.json msgid "pipe rifle: .38 Special" msgid_plural "pipe rifles: .38 Special" -msgstr[0] "" +msgstr[0] "自制钢管步枪(.38特制弹口径)" #: data/json/items/gun/38.json msgid "Ruger LCR .38" @@ -82417,7 +82659,7 @@ msgstr "" #: data/json/items/gun/380.json msgid "Taurus Spectrum" msgid_plural "Taurus Spectrum" -msgstr[0] "" +msgstr[0] "陶鲁斯\"光谱\"手枪" #: data/json/items/gun/380.json msgid "" @@ -82428,7 +82670,7 @@ msgstr "一把体积紧凑的 .38 口径手枪,在设计时极力强调隐蔽 #: data/json/items/gun/38super.json msgid "AF2011A1 .38 Super" msgid_plural "AF2011A1 .38 Super" -msgstr[0] "" +msgstr[0] "AF2011A1 .38 超级手枪" #: data/json/items/gun/38super.json msgid "" @@ -82459,7 +82701,7 @@ msgstr "M1911A1是一种非常流行的手枪,以其可靠性而闻名。这 #: data/json/items/gun/40.json msgid "Beretta 90-two .40 S&W" msgid_plural "Beretta 90-two .40 S&Ws" -msgstr[0] "" +msgstr[0] "伯莱塔 90-two .40 S&W 手枪" #: data/json/items/gun/40.json msgid "" @@ -82486,7 +82728,7 @@ msgstr "流行的格洛克 17 手槍的 .40 S&W 版本。是 FBI 與世界上無 #: data/json/items/gun/40.json msgid "Beretta Px4 Storm .40 S&W" msgid_plural "Beretta Px4 Storm .40 S&Ws" -msgstr[0] "" +msgstr[0] "伯莱塔 Px4 \"风暴\" .40 S&W 手枪" #: data/json/items/gun/40.json msgid "" @@ -82500,7 +82742,7 @@ msgstr "" #: data/json/items/gun/40.json msgid "pipe rifle: .40 S&W" msgid_plural "pipe rifles: .40 S&W" -msgstr[0] "" +msgstr[0] "自制钢管步枪(.40 S&W口径)" #: data/json/items/gun/40.json msgid "SIG Pro .40" @@ -82516,7 +82758,7 @@ msgstr "最主要是銷售給輕武裝人員用來接替舊式的 SIG 手槍, #: data/json/items/gun/40.json msgid "Luty SMG: .40 S&W" msgid_plural "Luty SMGs: .40 S&W" -msgstr[0] "" +msgstr[0] "Luty冲锋枪:.40 S&W弹" #: data/json/items/gun/40.json msgid "" @@ -82609,7 +82851,7 @@ msgstr "一把簡易的土炮榴彈發射器。基本上就是個鋼管加上擊 #: data/json/items/gun/40x46mm.json msgid "M320 standalone launcher" msgid_plural "M320 standalone launchers" -msgstr[0] "" +msgstr[0] "M320 榴弹发射器" #: data/json/items/gun/40x46mm.json msgid "" @@ -82676,7 +82918,7 @@ msgstr "多個" #: data/json/items/gun/40x46mm.json msgid "M203 array" msgid_plural "M203 arrays" -msgstr[0] "" +msgstr[0] "M203 榴弹阵列" #: data/json/items/gun/40x46mm.json msgid "" @@ -82686,7 +82928,7 @@ msgstr "在\"鹰爪\"型无人车平台上使用的六管 M203 榴弹发射器 #: data/json/items/gun/40x46mm.json data/mods/Aftershock/items/weapons.json msgid "deployed grenade launcher" msgid_plural "deployed grenade launchers" -msgstr[0] "" +msgstr[0] "榴弹发射器(展开)" #: data/json/items/gun/40x46mm.json msgid "" @@ -82722,7 +82964,7 @@ msgstr "Saiga-410是一把半自动霰弹枪,采用了与AK47相同的卡拉 #: data/json/items/gun/410shot.json msgid "Winchester M37 .410" msgid_plural "Winchester M37 .410s" -msgstr[0] "" +msgstr[0] "温彻斯特 M37 .410 霰弹枪" #: data/json/items/gun/410shot.json msgid "" @@ -82759,7 +83001,7 @@ msgstr "这把杠杆式步枪采用威力巨大的.44马格南弹药,一根造 #: data/json/items/gun/44.json msgid "pipe rifle: .44 Magnum" msgid_plural "pipe rifles: .44 Magnum" -msgstr[0] "" +msgstr[0] "自制钢管步枪(.44 马格南口径)" #: data/json/items/gun/44.json msgid "Ruger Redhawk" @@ -82888,7 +83130,7 @@ msgstr[0] ".45 鋼管步槍" #: data/json/items/gun/45.json msgid "Luty SMG: .45" msgid_plural "Luty SMGs: .45" -msgstr[0] "" +msgstr[0] "Luty冲锋枪:.45 弹" #: data/json/items/gun/45.json msgid "" @@ -82936,7 +83178,7 @@ msgstr[0] "USP .45" #: data/json/items/gun/45.json msgid "MK 23 MOD 0" msgid_plural "MK 23 MOD 0s" -msgstr[0] "" +msgstr[0] "MK 23 MOD 0 手枪" #: data/json/items/gun/45.json msgid "" @@ -82983,7 +83225,7 @@ msgstr "" #: data/json/items/gun/45.json msgid "Glock 21" msgid_plural "Glock 21s" -msgstr[0] "" +msgstr[0] "格洛克 21 手枪" #: data/json/items/gun/45.json msgid "" @@ -83005,7 +83247,7 @@ msgstr "蠻牛左輪手槍是一把 5 發裝左輪, 能夠發射 .454 卡蘇爾 #: data/json/items/gun/454.json msgid "Taurus Raging Judge Magnum" msgid_plural "Taurus Raging Judge Magnum" -msgstr[0] "" +msgstr[0] "陶鲁斯\"暴怒裁决\"左轮手枪" #: data/json/items/gun/454.json msgid "" @@ -83028,7 +83270,7 @@ msgstr "一种轻便但威力强大的杠杆式步枪,使用威力极大的 .4 #: data/json/items/gun/4570.json msgid "Magnum Research BFR" msgid_plural "Magnum Research BFRs" -msgstr[0] "" +msgstr[0] "马格南研究所 BFR 左轮手枪" #: data/json/items/gun/4570.json msgid "" @@ -83043,7 +83285,7 @@ msgstr "" #: data/json/items/gun/4570.json msgid "1874 Sharps" msgid_plural "1874 Sharps" -msgstr[0] "" +msgstr[0] "夏普斯 1874 型步枪" #: data/json/items/gun/4570.json msgid "" @@ -83058,7 +83300,7 @@ msgstr "" #: data/json/items/gun/45colt.json msgid "Bond Arms Derringer" msgid_plural "Bond Arms Derringers" -msgstr[0] "" +msgstr[0] "邦德军械厂德林加手枪" #: data/json/items/gun/45colt.json msgid "" @@ -83070,7 +83312,7 @@ msgstr "邦德军械厂德林加手枪是该系列的多管轻便型手枪型号 #: data/json/items/gun/45colt.json msgid "Colt Lightning .45 Carbine" msgid_plural "Colt Lightning .45 Carbines" -msgstr[0] "" +msgstr[0] "柯尔特\"闪电\" .45 卡宾枪" #: data/json/items/gun/45colt.json msgid "" @@ -83087,7 +83329,7 @@ msgstr "咔嚓。" #: data/json/items/gun/45colt.json msgid "Uberti Cattleman" msgid_plural "Uberti Cattleman" -msgstr[0] "" +msgstr[0] "乌贝蒂\"牛仔\"左轮手枪" #: data/json/items/gun/45colt.json msgid "" @@ -83116,7 +83358,7 @@ msgstr "为个人防卫武器设计,MP7拥有高射速,并使用4.6x30mm弹 #: data/json/items/gun/460.json msgid "1911-460" msgid_plural "1911-460s" -msgstr[0] "" +msgstr[0] "1911-460 手枪" #: data/json/items/gun/460.json msgid "" @@ -83213,7 +83455,7 @@ msgstr "由 Serbu 槍械公司製作的單發、採用栓動式槍機的步槍 #: data/json/items/gun/500.json msgid "Big Horn Model 89" msgid_plural "Big Horn Model 89" -msgstr[0] "" +msgstr[0] "大角羊 Model 89 步枪" #: data/json/items/gun/500.json msgid "" @@ -83406,7 +83648,7 @@ msgstr "" #: data/json/items/gun/762.json msgid "AK-47" msgid_plural "AK-47s" -msgstr[0] "" +msgstr[0] "AK-47 步枪" #: data/json/items/gun/762.json msgid "" @@ -83420,7 +83662,7 @@ msgstr "" #: data/json/items/gun/762.json msgid "Mini Draco" msgid_plural "Mini Dracos" -msgstr[0] "" +msgstr[0] "迷你 Draco 手枪" #: data/json/items/gun/762.json msgid "" @@ -83516,7 +83758,7 @@ msgstr "由瑞典製造, 卡爾古斯特M3無後座力砲是可以由後膛裝 #: data/json/items/gun/84x246mm.json msgid "AT4" msgid_plural "AT4s" -msgstr[0] "" +msgstr[0] "AT4 火箭筒" #: data/json/items/gun/84x246mm.json msgid "" @@ -83640,7 +83882,7 @@ msgstr "儘管有點誇張, RM99滿足了軍武狂熱者眼中的強大火力。 #: data/json/items/gun/9mm.json msgid "Beretta 90-two" msgid_plural "Beretta 90-twos" -msgstr[0] "" +msgstr[0] "伯莱塔 90-two 手枪" #: data/json/items/gun/9mm.json msgid "" @@ -83756,7 +83998,7 @@ msgstr "" #: data/json/items/gun/9mm.json msgid "H&K operational briefcase" msgid_plural "H&K operational briefcases" -msgstr[0] "" +msgstr[0] "H&K 特工手提箱" #: data/json/items/gun/9mm.json msgid "" @@ -83785,7 +84027,7 @@ msgstr "一把設計獨特的手槍口徑卡賓槍, 內置折疊式槍托, 使 #: data/json/items/gun/9mm.json msgid "Beretta M9A1" msgid_plural "Beretta M9A1" -msgstr[0] "" +msgstr[0] "伯莱塔 M9A1 手枪" #: data/json/items/gun/9mm.json msgid "" @@ -83800,7 +84042,7 @@ msgstr "" #: data/json/items/gun/9mm.json msgid "Beretta Px4 Storm" msgid_plural "Beretta Px4 Storms" -msgstr[0] "" +msgstr[0] "伯莱塔 Px4 \"风暴\"手枪" #: data/json/items/gun/9mm.json msgid "" @@ -83818,7 +84060,7 @@ msgstr[0] "9x19mm 鋼管步槍" #: data/json/items/gun/9mm.json msgid "Luty SMG: 9x19mm" msgid_plural "Luty SMGs: 9x19mm" -msgstr[0] "" +msgstr[0] "Luty冲锋枪: 9x19mm 弹" #: data/json/items/gun/9mm.json msgid "" @@ -84081,7 +84323,7 @@ msgstr[0] "雷射指槍" #: data/json/items/gun/bio.json data/json/mutations/mutations.json msgid "Assault barbs" msgid_plural "Assault barbs" -msgstr[0] "" +msgstr[0] "尖锐倒刺" #: data/json/items/gun/bio.json data/mods/No_Hope/Items/guns.json #: data/mods/No_Hope/Items/items_fake.json @@ -84319,7 +84561,7 @@ msgstr "一把装饰精美的燧发手枪。海盗船长们的标配之一。" #: data/json/items/gun/flintlock.json msgid "flintlock musket" msgid_plural "flintlock muskets" -msgstr[0] "" +msgstr[0] "燧发毛瑟枪" #: data/json/items/gun/flintlock.json msgid "" @@ -84398,7 +84640,7 @@ msgstr "一辆消防车上的水炮。安装在车辆上,可用于扑灭火灾 #: data/json/items/gun/monster_gun.json msgid "barb launching organ" msgid_plural "barb launching organs" -msgstr[0] "" +msgstr[0] "毒刺发射器官" #: data/json/items/gun/monster_gun.json msgid "A mutated organ capable of launching bony barbs at great speed." @@ -84426,7 +84668,7 @@ msgstr "一把供疯人车手用的虚拟霰弹枪(因为怪物瞄准太致命 #: data/json/items/gun/monster_gun.json msgid "electric alien frond" msgid_plural "electric alien fronds" -msgstr[0] "" +msgstr[0] "放电异界蕨叶" #: data/json/items/gun/monster_gun.json msgid "Electricity unnaturally arcs from the tips of this alien frond." @@ -84504,7 +84746,7 @@ msgstr "能夠裝填一發霰彈的手槍, 由廢料手工打造而成。" #: data/json/items/gun/shot.json msgid "12-gauge gatling gun" msgid_plural "12-gauge gatling guns" -msgstr[0] "" +msgstr[0] "12 号口径加特林霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84518,7 +84760,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Browning Auto 5" msgid_plural "Browning Auto 5s" -msgstr[0] "" +msgstr[0] "勃朗宁 Auto 5 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84545,7 +84787,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Kel-Tec KSG-25" msgid_plural "Kel-Tec KSG-25" -msgstr[0] "" +msgstr[0] "Kel-Tec KSG-25 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84578,7 +84820,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Mossberg 500 Field" msgid_plural "Mossberg 500 Field" -msgstr[0] "" +msgstr[0] "莫斯伯格 500 霰弹枪(野外型)" #: data/json/items/gun/shot.json msgid "" @@ -84591,7 +84833,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Mossberg 500 Security" msgid_plural "Mossberg 500 Security" -msgstr[0] "" +msgstr[0] "莫斯伯格 500 霰弹枪(安防型)" #: data/json/items/gun/shot.json msgid "" @@ -84604,7 +84846,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Mossberg 590A1" msgid_plural "Mossberg 590A1" -msgstr[0] "" +msgstr[0] "莫斯伯格 590A1 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84617,7 +84859,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Mossberg 930 SPX" msgid_plural "Mossberg 930 SPXs" -msgstr[0] "" +msgstr[0] "莫斯伯格 930 SPX 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84653,7 +84895,7 @@ msgstr "一把土炮的霰彈槍。簡單地把鋼管連接到有擊鎚的彈倉 #: data/json/items/gun/shot.json msgid "Remington 870 Wingmaster" msgid_plural "Remington 870 Wingmaster" -msgstr[0] "" +msgstr[0] "雷明顿 870 \"翼主\"霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84668,7 +84910,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Remington 870 MCS" msgid_plural "Remington 870 MCSs" -msgstr[0] "" +msgstr[0] "雷明顿 870 MCS 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84684,7 +84926,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Remington 870 express" msgid_plural "Remington 870 expresses" -msgstr[0] "" +msgstr[0] "雷明顿 870 \"急速\"霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84765,7 +85007,7 @@ msgstr "一把舊式的霰彈槍, 可能是個古董。是個槍管, 槍機, 擊 #: data/json/items/gun/shot.json msgid "Cobray Streetsweeper" msgid_plural "Cobray Streetsweepers" -msgstr[0] "" +msgstr[0] "科布雷\"清道夫\"霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84786,7 +85028,7 @@ msgstr "3 連發" #: data/json/items/gun/shot.json msgid "Franchi SPAS-12" msgid_plural "Franchi SPAS-12s" -msgstr[0] "" +msgstr[0] "弗兰齐 SPAS-12 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84802,7 +85044,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "Tavor TS12" msgid_plural "Tavor TS12s" -msgstr[0] "" +msgstr[0] "塔沃尔 TS12 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84817,7 +85059,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "USAS 12" msgid_plural "USAS 12s" -msgstr[0] "" +msgstr[0] "USAS 12 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84832,7 +85074,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "1887 bootleg shotgun" msgid_plural "1887 bootleg shotguns" -msgstr[0] "" +msgstr[0] "仿制 1887 霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84849,7 +85091,7 @@ msgstr "" #: data/json/items/gun/shot.json msgid "M1897 Trench Gun" msgid_plural "M1897 Trench Guns" -msgstr[0] "" +msgstr[0] "M1897 堑壕霰弹枪" #: data/json/items/gun/shot.json msgid "" @@ -84886,7 +85128,7 @@ msgstr "由研發機構 \"航天實驗室\" 開發的強力電子雷射。在對 #: data/json/items/gun/ups.json msgid "CMES laser cannon" msgid_plural "CMES laser cannons" -msgstr[0] "" +msgstr[0] "CMES 激光炮" #: data/json/items/gun/ups.json msgid "" @@ -84912,7 +85154,7 @@ msgstr "" #: data/json/items/gun/ups.json msgid "RMES marksman system" msgid_plural "RMES marksman systems" -msgstr[0] "" +msgstr[0] "RMES 狙击系统" #: data/json/items/gun/ups.json msgid "" @@ -85031,7 +85273,7 @@ msgstr "安定器" #: data/json/items/gunmod/accessories.json msgid "belt clip" msgid_plural "belt clips" -msgstr[0] "" +msgstr[0] "皮带夹" #: data/json/items/gunmod/accessories.json msgid "" @@ -85104,7 +85346,7 @@ msgstr "用来测试 UPS 消耗的枪械模组,它不会被正常生成。增 #: data/json/items/gunmod/bionicmods.json msgid "Power shot" msgid_plural "Power shots" -msgstr[0] "" +msgstr[0] "强力射击" #: data/json/items/gunmod/bionicmods.json msgid "" @@ -85197,7 +85439,7 @@ msgstr "一套符合人體工學的替換組件,用於改善槍械的操控性 #: data/json/items/gunmod/grip.json msgid "breacher grip" msgid_plural "breacher grips" -msgstr[0] "" +msgstr[0] "破门握把" #: data/json/items/gunmod/grip.json msgid "" @@ -85223,7 +85465,7 @@ msgstr "晶體" #: data/json/items/gunmod/laser_gunmods.json msgid "focusing lens" msgid_plural "focusing lenses" -msgstr[0] "" +msgstr[0] "聚焦透镜" #: data/json/items/gunmod/laser_gunmods.json msgid "" @@ -85273,7 +85515,7 @@ msgstr "一个使用了高能量密度材质制成的电容器,能够增加激 #: data/mods/Generic_Guns/gunmods/gunmods.json msgid "speedloader chute" msgid_plural "speedloader chutes" -msgstr[0] "" +msgstr[0] "快速装弹器滑槽" #: data/json/items/gunmod/loading_port.json #: data/mods/Generic_Guns/gunmods/gunmods.json @@ -85305,7 +85547,7 @@ msgstr "機件" #: data/json/items/gunmod/mechanism.json msgid "drop-in auto sear" msgid_plural "drop-in auto sears" -msgstr[0] "" +msgstr[0] "插入式自动扳机" #: data/json/items/gunmod/mechanism.json msgid "" @@ -85319,7 +85561,7 @@ msgstr "" #: data/json/items/gunmod/mechanism.json msgid "lightning link" msgid_plural "lightning links" -msgstr[0] "" +msgstr[0] "\"闪电链\"扳机" #: data/json/items/gunmod/mechanism.json msgid "" @@ -85347,7 +85589,7 @@ msgstr "一套防水膠布和墊圈, 讓槍械在水中也能正常使用。" #: data/json/items/gunmod/mount.json msgid "replaceable furniture kit" msgid_plural "replaceable furniture kits" -msgstr[0] "" +msgstr[0] "可更换枪具套装" #: data/json/items/gunmod/mount.json msgid "" @@ -85365,7 +85607,7 @@ msgstr "握把底座" #: data/json/items/gunmod/mount.json msgid "side mount" msgid_plural "side mounts" -msgstr[0] "" +msgstr[0] "导轨底座" #: data/json/items/gunmod/mount.json msgid "" @@ -85381,7 +85623,7 @@ msgstr "导轨底座" #: data/json/items/gunmod/mount.json msgid "sights mount" msgid_plural "sights mounts" -msgstr[0] "" +msgstr[0] "瞄具底座" #: data/json/items/gunmod/mount.json msgid "" @@ -85395,7 +85637,7 @@ msgstr "" #: data/json/items/gunmod/mount.json msgid "launcher sights mount" msgid_plural "launcher sights mounts" -msgstr[0] "" +msgstr[0] "发射器瞄具底座" #: data/json/items/gunmod/mount.json msgid "" @@ -85407,7 +85649,7 @@ msgstr "这是一个塑料支架,用于安装各种瞄具模组,设计能永 #: data/json/items/gunmod/mount.json msgid "pistol sights mount" msgid_plural "pistol sights mounts" -msgstr[0] "" +msgstr[0] "手枪瞄具底座" #: data/json/items/gunmod/mount.json msgid "" @@ -85419,7 +85661,7 @@ msgstr "这是一个塑料支架,用于安装各种瞄具模组,设计能永 #: data/json/items/gunmod/mount.json msgid "replaceable stock kit" msgid_plural "replaceable stock kits" -msgstr[0] "" +msgstr[0] "可更换枪托套装" #: data/json/items/gunmod/mount.json msgid "" @@ -85438,7 +85680,7 @@ msgstr "枪托底座" #: data/json/items/gunmod/mount.json msgid "bottom mount" msgid_plural "bottom mounts" -msgstr[0] "" +msgstr[0] "管下底座" #: data/json/items/gunmod/mount.json msgid "" @@ -85481,7 +85723,7 @@ msgstr "砲口制退器重新定向排氣, 減少砲口上揚和降低後坐力, #: data/json/items/gunmod/muzzle.json msgid "modified muzzle brake" msgid_plural "modified muzzle brakes" -msgstr[0] "" +msgstr[0] "改装枪口制退器" #: data/json/items/gunmod/muzzle.json msgid "" @@ -85513,7 +85755,7 @@ msgstr "" #: data/json/items/gunmod/muzzle.json msgid "'solvent trap' suppressor" msgid_plural "'solvent trap' suppressors" -msgstr[0] "" +msgstr[0] "\"溶剂陷阱\"消音器" #: data/json/items/gunmod/muzzle.json msgid "" @@ -85530,7 +85772,7 @@ msgstr "" #: data/json/items/gunmod/muzzle.json msgid "soda bottle silencer" msgid_plural "soda bottle silencers" -msgstr[0] "" +msgstr[0] "苏打瓶消音器" #: data/json/items/gunmod/muzzle.json msgid "" @@ -85626,7 +85868,7 @@ msgstr "滑軌" #: data/json/items/gunmod/rail.json msgid "modified rail-mounted crossbow" msgid_plural "modified rail-mounted crossbows" -msgstr[0] "" +msgstr[0] "改装劲弩组件" #: data/json/items/gunmod/rail.json msgid "" @@ -85650,7 +85892,7 @@ msgstr "一個45° 傾側的偏移覘孔, 應用於被瞄準鏡或其他改造 #: data/json/items/gunmod/rail.json msgid "modified offset iron sights" msgid_plural "modified offset iron sights" -msgstr[0] "" +msgstr[0] "改装侧面机械瞄具" #: data/json/items/gunmod/rail.json msgid "" @@ -85663,7 +85905,7 @@ msgstr "" #: data/json/items/gunmod/rail.json msgid "offset sight rail" msgid_plural "offset sight rails" -msgstr[0] "" +msgstr[0] "侧面瞄具导轨" #: data/json/items/gunmod/rail.json msgid "An additional rail set at 45° for attaching a secondary optic." @@ -85672,7 +85914,7 @@ msgstr "一组以垂直枪械平面45度角安装到枪械侧面上的导轨, #: data/json/items/gunmod/rail.json msgid "modified offset sight rail" msgid_plural "modified offset sight rails" -msgstr[0] "" +msgstr[0] "改装侧面瞄具导轨" #: data/json/items/gunmod/rail.json msgid "" @@ -85706,7 +85948,7 @@ msgstr "一个安装在枪械侧面的高级模组,可减轻枪械震动,极 #: data/json/items/gunmod/rail.json msgid "modified gyroscopic stabilizer" msgid_plural "modified gyroscopic stabilizers" -msgstr[0] "" +msgstr[0] "改装稳定陀螺仪" #: data/json/items/gunmod/rail.json msgid "" @@ -85812,7 +86054,7 @@ msgstr "一个 3-18x44 步枪瞄准器。它可以按 1/10 毫弧度增量调节 #: data/json/items/gunmod/sights.json msgid "modified rifle scope" msgid_plural "modified rifle scopes" -msgstr[0] "" +msgstr[0] "改装步枪瞄准镜" #: data/json/items/gunmod/sights.json msgid "" @@ -85838,7 +86080,7 @@ msgstr "一个 4x32 TA01 型先进战斗光学瞄准镜(ACOG),带有一个 #: data/json/items/gunmod/sights.json msgid "modified ACOG scope" msgid_plural "modified ACOG scopes" -msgstr[0] "" +msgstr[0] "改装 ACOG 瞄准镜" #: data/json/items/gunmod/sights.json msgid "" @@ -85926,7 +86168,7 @@ msgstr "一個折疊式槍托, 體積較小, 但需要在使用前展開。增 #: data/json/items/gunmod/stock.json msgid "folding wire stock" msgid_plural "folding wire stocks" -msgstr[0] "" +msgstr[0] "折叠式铁丝枪托" #: data/json/items/gunmod/stock.json msgid "" @@ -85992,7 +86234,7 @@ msgstr "兩腳架通常用於步槍與機槍, 用來減少槍管的晃動。雖 #: data/json/items/gunmod/underbarrel.json msgid "modified bipod" msgid_plural "modified bipods" -msgstr[0] "" +msgstr[0] "改装双脚架" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86040,7 +86282,7 @@ msgstr "安裝於槍管上的前置握把可以增加槍枝的穩定度與準確 #: data/json/items/gunmod/underbarrel.json msgid "modified forward grip" msgid_plural "modified forward grips" -msgstr[0] "" +msgstr[0] "改装前置握把" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86077,7 +86319,7 @@ msgstr "整合在 Kel-Tec KSG 上的副彈匣, 能容納七發彈藥。它並不 #: data/json/items/gunmod/underbarrel.json msgid "KSG-25 second magazine" msgid_plural "KSG-25 second magazines" -msgstr[0] "" +msgstr[0] "KSG-25霰弹枪第二弹仓" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86088,7 +86330,7 @@ msgstr "KSG-25 霰弹枪集成的第二弹匣,能容纳12发霰弹。无法拆 #: data/json/items/gunmod/underbarrel.json msgid "TS12 second magazine" msgid_plural "TS12 second magazines" -msgstr[0] "" +msgstr[0] "TS12 霰弹枪第二弹仓" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86099,7 +86341,7 @@ msgstr "塔沃尔 TS12 霰弹枪集成的第二弹匣,能容纳5发霰弹。 #: data/json/items/gunmod/underbarrel.json msgid "TS12 third magazine" msgid_plural "TS12 third magazines" -msgstr[0] "" +msgstr[0] "TS12 霰弹枪第三弹仓" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86146,7 +86388,7 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "modified M203" msgid_plural "modified M203s" -msgstr[0] "" +msgstr[0] "改装 M203 榴弹发射器" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86174,7 +86416,7 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "modified M320 GLM" msgid_plural "modified M320 GLMs" -msgstr[0] "" +msgstr[0] "改装 M320 榴弹发射器" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86189,7 +86431,7 @@ msgstr "" #: data/json/items/gunmod/underbarrel.json msgid "M6 Survival Gun shotgun" msgid_plural "M6 Survival Gun shotguns" -msgstr[0] "" +msgstr[0] "M6 生存步枪霰弹枪" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86224,7 +86466,7 @@ msgstr "可以掛載於任一款步槍的霰彈槍模組, 一次能夠裝填 4 #: data/json/items/gunmod/underbarrel.json msgid "modified masterkey shotgun" msgid_plural "modified masterkey shotguns" -msgstr[0] "" +msgstr[0] "改装多用霰弹副枪" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86272,7 +86514,7 @@ msgstr "Rivtech RM121 附掛武器系統是一個彈匣供彈的半自動無殼 #: data/json/items/gunmod/underbarrel.json msgid "modified RM121 aux shotgun" msgid_plural "modified RM121 aux shotguns" -msgstr[0] "" +msgstr[0] "改装 RM121 副枪" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86298,7 +86540,7 @@ msgstr "一個雙管霰彈槍, 能夠附掛在許多步槍的槍管下。一次 #: data/json/items/gunmod/underbarrel.json msgid "modified underslung shotgun" msgid_plural "modified underslung shotguns" -msgstr[0] "" +msgstr[0] "改装下挂式霰弹副枪" #: data/json/items/gunmod/underbarrel.json msgid "" @@ -86311,7 +86553,7 @@ msgstr "枪管很短的双管霰弹枪,它可以被安装在多种步枪的枪 #: data/json/items/magazine/12mm.json msgid "H&K G80 magazine" msgid_plural "H&K G80 magazines" -msgstr[0] "" +msgstr[0] "H&K G80 磁轨枪弹匣" #. ~ Description for {'str': 'H&K G80 magazine'} #: data/json/items/magazine/12mm.json @@ -86323,7 +86565,7 @@ msgstr "一个可用于H&K G80轨道步枪的弹匣,容量为20发磁轨弹。 #: data/json/items/magazine/20x60mm.json msgid "RMSA10 20x66mm compact magazine" msgid_plural "RMSA10 20x66mm compact magazines" -msgstr[0] "" +msgstr[0] "RMSA10 20x66mm紧凑型弹匣" #. ~ Description for {'str': 'RMSA10 20x66mm compact magazine'} #: data/json/items/magazine/20x60mm.json @@ -86335,7 +86577,7 @@ msgstr "一個 10 發的盒型彈匣, 適用於 RM228 PDW 及 RM121 附掛霰彈 #: data/json/items/magazine/20x60mm.json msgid "RMSB20 20x66mm magazine" msgid_plural "RMSB20 20x66mm magazines" -msgstr[0] "" +msgstr[0] "RMSB20 20x66mm 弹匣" #. ~ Description for {'str': 'RMSB20 20x66mm magazine'} #: data/json/items/magazine/20x60mm.json @@ -86345,7 +86587,7 @@ msgstr "一個 20 發的盒型彈匣, 適用於 RM20 無殼霰彈槍。" #: data/json/items/magazine/20x60mm.json msgid "RMSB40 20x66mm extended magazine" msgid_plural "RMSB40 20x66mm extended magazines" -msgstr[0] "" +msgstr[0] "RMSB40 20x66mm 扩充弹匣" #. ~ Description for {'str': 'RMSB40 20x66mm extended magazine'} #: data/json/items/magazine/20x60mm.json @@ -86355,7 +86597,7 @@ msgstr "一個 40 發的盒型彈匣, 適用於 RM20 無殼霰彈槍。" #: data/json/items/magazine/22.json msgid ".22 8-round speedloader" msgid_plural ".22 8-round speedloaders" -msgstr[0] "" +msgstr[0] "8发快速装弹器(.22口径)" #. ~ Description for {'str': '.22 8-round speedloader'} #: data/json/items/magazine/22.json @@ -86367,7 +86609,7 @@ msgstr "這個快速裝填器可以容納8發.22子彈,用來快速重新裝 #: data/json/items/magazine/22.json msgid "A-180 magazine" msgid_plural "A-180 magazines" -msgstr[0] "" +msgstr[0] "A-180 弹匣" #. ~ Description for {'str': 'A-180 magazine'} #: data/json/items/magazine/22.json @@ -86377,7 +86619,7 @@ msgstr "一個特殊形狀的彈盤, 適用於 American-180 衝鋒槍。" #: data/json/items/magazine/22.json msgid ".22 19-round tube speedloader" msgid_plural ".22 19-round tube speedloaders" -msgstr[0] "" +msgstr[0] "19发管状快速装弹器(.22口径)" #. ~ Description for {'str': '.22 19-round tube speedloader'} #: data/json/items/magazine/22.json @@ -86389,7 +86631,7 @@ msgstr "這是一個可以容納19發.22子彈的管子,用於快速重新裝 #: data/json/items/magazine/22.json msgid "SIG Mosquito magazine" msgid_plural "SIG Mosquito magazines" -msgstr[0] "" +msgstr[0] "西格&绍尔\"蚊\"式手枪弹匣" #. ~ Description for {'str': 'SIG Mosquito magazine'} #: data/json/items/magazine/22.json @@ -86399,7 +86641,7 @@ msgstr "一個工廠規格的 10 發彈匣, 適用於 SIG Mosquito 手槍。" #: data/json/items/magazine/22.json msgid "Ruger BX-25 magazine" msgid_plural "Ruger BX-25 magazines" -msgstr[0] "" +msgstr[0] "鲁格 BX-25 弹匣" #. ~ Description for {'str': 'Ruger BX-25 magazine'} #: data/json/items/magazine/22.json @@ -86409,7 +86651,7 @@ msgstr "適用於魯格 10/22 的加長型 25 發條狀彈匣。" #: data/json/items/magazine/22.json msgid "Ruger 10/22 rotary magazine" msgid_plural "Ruger 10/22 rotary magazines" -msgstr[0] "" +msgstr[0] "鲁格 10/22 螺旋弹匣" #. ~ Description for {'str': 'Ruger 10/22 rotary magazine'} #: data/json/items/magazine/22.json @@ -86421,7 +86663,7 @@ msgstr "一個 10 發的可拆卸旋轉式彈匣, 適用於魯格 10/22, 彈匣 #: data/json/items/magazine/22.json msgid "S&W 22A magazine" msgid_plural "S&W 22A magazines" -msgstr[0] "" +msgstr[0] "S&W 22A 弹匣" #. ~ Description for {'str': 'S&W 22A magazine'} #: data/json/items/magazine/22.json @@ -86431,7 +86673,7 @@ msgstr "一個標準容量的彈匣, 適用於流行的 S&W 22A 手槍。" #: data/json/items/magazine/22.json msgid "Jennings J-22 magazine" msgid_plural "Jennings J-22 magazines" -msgstr[0] "" +msgstr[0] "詹宁斯 J-22 手枪弹匣" #. ~ Description for {'str': 'Jennings J-22 magazine'} #: data/json/items/magazine/22.json @@ -86441,7 +86683,7 @@ msgstr "Jennings J-22 手槍使用的便宜六發裝鋼製盒狀彈匣。" #: data/json/items/magazine/22.json msgid "Walther P22 magazine" msgid_plural "Walther P22 magazines" -msgstr[0] "" +msgstr[0] "瓦尔特 P22 手枪弹匣" #. ~ Description for {'str': 'Walther P22 magazine'} #: data/json/items/magazine/22.json @@ -86451,12 +86693,12 @@ msgstr "一個 10 發裝的盒式彈匣,適用於華瑟 P22 手槍。" #: data/json/items/magazine/223.json msgid "5.56x45mm ammo belt" msgid_plural "5.56x45mm ammo belts" -msgstr[0] "" +msgstr[0] "5.56x45mm 子弹带" #: data/json/items/magazine/223.json msgid "MAS 223 magazine" msgid_plural "MAS 223 magazines" -msgstr[0] "" +msgstr[0] "MAS 223 弹匣" #. ~ Description for {'str': 'MAS 223 magazine'} #: data/json/items/magazine/223.json @@ -86478,7 +86720,7 @@ msgstr "一个紧凑的5发盒式弹匣,可用于鲁格Mini-14步枪上。" #: data/json/items/magazine/223.json msgid "STANAG 10-round magazine" msgid_plural "STANAG 10-round magazines" -msgstr[0] "" +msgstr[0] "STANAG 10发弹匣" #. ~ Description for {'str': 'STANAG 10-round magazine'} #: data/json/items/magazine/223.json @@ -86540,7 +86782,7 @@ msgstr "一个笨重的100发双排弹鼓,可用于鲁格Mini-14步枪上。" #: data/json/items/magazine/223.json msgid "STANAG 5-round magazine" msgid_plural "STANAG 5-round magazines" -msgstr[0] "" +msgstr[0] "STANAG 5发弹匣" #. ~ Description for {'str': 'STANAG 5-round magazine'} #: data/json/items/magazine/223.json @@ -86551,7 +86793,7 @@ msgstr "一个非常紧凑的5发盒式弹匣,用于能兼容STANAG弹匣的 #: data/json/items/magazine/223.json msgid "STANAG 20-round magazine" msgid_plural "STANAG 20-round magazines" -msgstr[0] "" +msgstr[0] "STANAG 20发弹匣" #. ~ Description for {'str': 'STANAG 20-round magazine'} #: data/json/items/magazine/223.json @@ -86561,7 +86803,7 @@ msgstr "一个紧凑的20发盒式弹匣,用于能兼容STANAG弹匣的步枪 #: data/json/items/magazine/223.json msgid "STANAG 30-round magazine" msgid_plural "STANAG 30-round magazines" -msgstr[0] "" +msgstr[0] "STANAG 30发弹匣" #. ~ Description for {'str': 'STANAG 30-round magazine'} #: data/json/items/magazine/223.json @@ -86573,7 +86815,7 @@ msgstr "一个标准容量的30发盒式弹匣,可用于能兼容STANAG弹匣 #: data/json/items/magazine/223.json msgid "STANAG 40-round magazine" msgid_plural "STANAG 40-round magazines" -msgstr[0] "" +msgstr[0] "STANAG 40发弹匣" #. ~ Description for {'str': 'STANAG 40-round magazine'} #: data/json/items/magazine/223.json @@ -86585,7 +86827,7 @@ msgstr "一个增大容量的40发盒式弹匣,可用于能兼容STANAG弹匣 #: data/json/items/magazine/223.json msgid "STANAG 50-round drum magazine" msgid_plural "STANAG 50-round drum magazines" -msgstr[0] "" +msgstr[0] "STANAG 50发弹鼓" #. ~ Description for {'str': 'STANAG 50-round drum magazine'} #: data/json/items/magazine/223.json @@ -86597,7 +86839,7 @@ msgstr "一个笨重的50发弹鼓,用于能兼容STANAG弹匣步枪。它的 #: data/json/items/magazine/223.json msgid "STANAG 60-round magazine" msgid_plural "STANAG 60-round magazines" -msgstr[0] "" +msgstr[0] "STANAG 60发弹匣" #. ~ Description for {'str': 'STANAG 60-round magazine'} #: data/json/items/magazine/223.json @@ -86609,7 +86851,7 @@ msgstr "一个高容量的60发盒式弹匣,用于能兼容STANAG弹匣的步 #: data/json/items/magazine/223.json msgid "STANAG 60-round drum magazine" msgid_plural "STANAG 60-round drum magazines" -msgstr[0] "" +msgstr[0] "STANAG 60发弹鼓" #. ~ Description for {'str': 'STANAG 60-round drum magazine'} #: data/json/items/magazine/223.json @@ -86621,7 +86863,7 @@ msgstr "一个笨重的60发弹鼓,用于能兼容STANAG弹匣的步枪。它 #: data/json/items/magazine/223.json msgid "STANAG 90-round snail drum magazine" msgid_plural "STANAG 90-round snail drum magazines" -msgstr[0] "" +msgstr[0] "STANAG 90发弹鼓" #. ~ Description for {'str': 'STANAG 90-round snail drum magazine'} #: data/json/items/magazine/223.json @@ -86632,7 +86874,7 @@ msgstr "一个笨重的90发蜗式弹鼓,用于能兼容STANAG弹匣的步枪 #: data/json/items/magazine/223.json msgid "STANAG 100-round magazine" msgid_plural "STANAG 100-round magazines" -msgstr[0] "" +msgstr[0] "STANAG 100发弹匣" #. ~ Description for {'str': 'STANAG 100-round magazine'} #: data/json/items/magazine/223.json @@ -86644,7 +86886,7 @@ msgstr "一个高容量的100发盒式弹匣,用于能兼容STANAG弹匣的步 #: data/json/items/magazine/223.json msgid "STANAG 100-round double drum magazine" msgid_plural "STANAG 100-round double drum magazines" -msgstr[0] "" +msgstr[0] "STANAG 100发弹鼓" #. ~ Description for {'str': 'STANAG 100-round double drum magazine'} #: data/json/items/magazine/223.json @@ -86656,7 +86898,7 @@ msgstr "一个笨重的100发双排弹鼓,用于能兼容STANAG弹匣步枪。 #: data/json/items/magazine/223.json msgid "STANAG 150-round double drum magazine" msgid_plural "STANAG 150-round double drum magazines" -msgstr[0] "" +msgstr[0] "STANAG 150发弹鼓" #. ~ Description for {'str': 'STANAG 150-round double drum magazine'} #: data/json/items/magazine/223.json @@ -86668,7 +86910,7 @@ msgstr "一个笨重的150发双排弹鼓,用于能兼容STANAG弹匣步枪。 #: data/json/items/magazine/223.json msgid "G36 30-round magazine" msgid_plural "G36 30-round magazines" -msgstr[0] "" +msgstr[0] "G36 30发弹匣" #. ~ Description for {'str': 'G36 30-round magazine'} #: data/json/items/magazine/223.json @@ -86678,7 +86920,7 @@ msgstr "一个标准容量的30发盒式弹匣,可用于G36突击步枪上。" #: data/json/items/magazine/223.json msgid "G36 100-round double drum magazine" msgid_plural "G36 100-round double drum magazines" -msgstr[0] "" +msgstr[0] "G36 100发弹鼓" #. ~ Description for {'str': 'G36 100-round double drum magazine'} #: data/json/items/magazine/223.json @@ -86689,7 +86931,7 @@ msgstr "一个笨重的100发双排弹鼓,可用于G36突击步枪上。" #: data/json/items/magazine/223.json msgid "AUG 10-round magazine" msgid_plural "AUG 10-round magazines" -msgstr[0] "" +msgstr[0] "AUG 10发弹匣" #. ~ Description for {'str': 'AUG 10-round magazine'} #: data/json/items/magazine/223.json @@ -86700,7 +86942,7 @@ msgstr "一个紧凑的10发盒式弹匣,可用于斯泰尔 AUG 突击步枪 #: data/json/items/magazine/223.json msgid "AUG 30-round magazine" msgid_plural "AUG 30-round magazines" -msgstr[0] "" +msgstr[0] "AUG 30发弹匣" #. ~ Description for {'str': 'AUG 30-round magazine'} #: data/json/items/magazine/223.json @@ -86712,7 +86954,7 @@ msgstr "一个标准容量的30发盒式弹匣,可用于斯泰尔 AUG 突击 #: data/json/items/magazine/223.json msgid "AUG 42-round magazine" msgid_plural "AUG 42-round magazines" -msgstr[0] "" +msgstr[0] "AUG 42发弹匣" #. ~ Description for {'str': 'AUG 42-round magazine'} #: data/json/items/magazine/223.json @@ -86724,7 +86966,7 @@ msgstr "一个增大容量的42发盒式弹匣,可用于斯泰尔 AUG 突击 #: data/json/items/magazine/223.json msgid "AUG 100-round double drum magazine" msgid_plural "AUG 100-round double drum magazines" -msgstr[0] "" +msgstr[0] "AUG 100发弹鼓" #. ~ Description for {'str': 'AUG 100-round double drum magazine'} #: data/json/items/magazine/223.json @@ -86737,7 +86979,7 @@ msgstr "一个笨重的100发双排弹鼓,可用于斯泰尔 AUG 突击步枪 #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "STANAG makeshift magazine" msgid_plural "STANAG makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 STANAG 北约制式弹匣" #. ~ Description for {'str': 'STANAG makeshift magazine'} #: data/json/items/magazine/223.json @@ -86751,7 +86993,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "Ruger makeshift magazine" msgid_plural "Ruger makeshift magazines" -msgstr[0] "" +msgstr[0] "自制鲁格步枪弹匣" #. ~ Description for {'str': 'Ruger makeshift magazine'} #: data/json/items/magazine/223.json @@ -86764,7 +87006,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/json/items/magazine/300.json msgid "M2010 ESR magazine" msgid_plural "M2010 ESR magazines" -msgstr[0] "" +msgstr[0] "M2010 ESR 步枪弹匣" #. ~ Description for {'str': 'M2010 ESR magazine'} #: data/json/items/magazine/300.json @@ -86774,7 +87016,7 @@ msgstr "一個 5 發盒狀彈匣, 適用於 M2010 ESR 狙擊槍。" #: data/json/items/magazine/3006.json msgid ".30-06 clip" msgid_plural ".30-06 clips" -msgstr[0] "" +msgstr[0] ".30-06 弹夹" #. ~ Description for {'str': '.30-06 clip'} #. ~ Description for {'str': '7.62x39mm clip'} @@ -86789,7 +87031,7 @@ msgstr "一小塊帶溝槽的金屬,設計用於讓射擊者快速裝填拴式 #: data/json/items/magazine/3006.json msgid "Browning BLR magazine" msgid_plural "Browning BLR magazines" -msgstr[0] "" +msgstr[0] "勃朗宁BLR步枪弹匣" #. ~ Description for {'str': 'Browning BLR magazine'} #: data/json/items/magazine/3006.json @@ -86799,7 +87041,7 @@ msgstr "一個簡潔精巧的 4 發盒狀彈匣, 適用於白朗寧 BLR 步槍 #: data/json/items/magazine/3006.json msgid "M1 Garand clip" msgid_plural "M1 Garand clips" -msgstr[0] "" +msgstr[0] "M1加兰德 步枪弹夹" #. ~ Description for {'str': 'M1 Garand clip'} #: data/json/items/magazine/3006.json @@ -86811,7 +87053,7 @@ msgstr "一條用於 M1 加蘭德步槍的輕便漏夾, 當子彈打光時漏夾 #: data/json/items/magazine/3006.json msgid "BAR extended magazine" msgid_plural "BAR extended magazines" -msgstr[0] "" +msgstr[0] "勃朗宁自动步枪扩充弹匣" #. ~ Description for {'str': 'BAR extended magazine'} #: data/json/items/magazine/3006.json @@ -86823,7 +87065,7 @@ msgstr "一個適用於白朗寧自動步槍的非原廠彈匣, 能容納 30 發 #: data/json/items/magazine/3006.json msgid "BAR magazine" msgid_plural "BAR magazines" -msgstr[0] "" +msgstr[0] "勃朗宁BAR步枪弹匣" #. ~ Description for {'str': 'BAR magazine'} #: data/json/items/magazine/3006.json @@ -86837,13 +87079,13 @@ msgstr "一個適用於白朗寧自動步槍的標準容量彈匣, 能容納 20 #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "7.62x51mm ammo belt" msgid_plural "7.62x51mm ammo belts" -msgstr[0] "" +msgstr[0] "7.62x51mm 子弹带" #: data/json/items/magazine/308.json #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "FN FAL extended magazine" msgid_plural "FN FAL extended magazines" -msgstr[0] "" +msgstr[0] "FN FAL 步枪扩充弹匣" #. ~ Description for {'str': 'FN FAL extended magazine'} #: data/json/items/magazine/308.json @@ -86854,7 +87096,7 @@ msgstr "一個加長的 30 發鋼製盒狀彈匣, 適用於 FN FAL 自動步槍 #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "FN FAL magazine" msgid_plural "FN FAL magazines" -msgstr[0] "" +msgstr[0] "FN FAL 步枪弹匣" #. ~ Description for {'str': 'FN FAL magazine'} #: data/json/items/magazine/308.json @@ -86865,7 +87107,7 @@ msgstr "一個由軍方配給的 20 發鋼製盒狀彈匣, 適用於 FN FAL 自 #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "FN FAL makeshift magazine" msgid_plural "FN FAL makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 FN FAL 步枪弹匣" #. ~ Description for {'str': 'FN FAL makeshift magazine'} #: data/json/items/magazine/308.json @@ -86879,7 +87121,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "H&K G3 drum magazine" msgid_plural "H&K G3 drum magazines" -msgstr[0] "" +msgstr[0] "H&K G3 步枪弹鼓" #. ~ Description for {'str': 'H&K G3 drum magazine'} #: data/json/items/magazine/308.json @@ -86890,7 +87132,7 @@ msgstr "50发弹鼓,可用于H&K G3步枪。" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "H&K G3 magazine" msgid_plural "H&K G3 magazines" -msgstr[0] "" +msgstr[0] "H&K G3 步枪弹匣" #. ~ Description for {'str': 'H&K G3 magazine'} #: data/json/items/magazine/308.json @@ -86901,7 +87143,7 @@ msgstr "一個輕巧的鋁製盒狀彈匣, 適用於 H&K G3 步槍。" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "H&K G3 makeshift magazine" msgid_plural "H&K G3 makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 H&K G3 步枪弹匣" #. ~ Description for {'str': 'H&K G3 makeshift magazine'} #: data/json/items/magazine/308.json @@ -86915,7 +87157,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "M14 magazine" msgid_plural "M14 magazines" -msgstr[0] "" +msgstr[0] "M14 步枪弹匣" #. ~ Description for {'str': 'M14 magazine'} #: data/json/items/magazine/308.json @@ -86928,7 +87170,7 @@ msgstr "一個由軍方配給的 20 發鋼製盒狀彈匣, 適用於 M14 系列 #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "M14 compact magazine" msgid_plural "M14 compact magazines" -msgstr[0] "" +msgstr[0] "M14 步枪紧凑型弹匣" #. ~ Description for {'str': 'M14 compact magazine'} #: data/json/items/magazine/308.json @@ -86942,7 +87184,7 @@ msgstr "5发弹匣,一个紧凑的代用钢制弹匣,可用于M14步枪及 #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "M14 makeshift magazine" msgid_plural "M14 makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 M14 步枪弹匣" #. ~ Description for {'str': 'M14 makeshift magazine'} #: data/json/items/magazine/308.json @@ -86956,7 +87198,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "FN SCAR-H drum magazine" msgid_plural "FN SCAR-H drum magazines" -msgstr[0] "" +msgstr[0] "FN SCAR-H 步枪弹鼓" #. ~ Description for {'str': 'FN SCAR-H drum magazine'} #: data/json/items/magazine/308.json @@ -86967,7 +87209,7 @@ msgstr "50发弹鼓,可用于FN SCAR-H步枪。" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "FN SCAR-H 30-round magazine" msgid_plural "FN SCAR-H 30-round magazines" -msgstr[0] "" +msgstr[0] "FN SCAR-H 30发弹匣" #. ~ Description for {'str': 'FN SCAR-H 30-round magazine'} #: data/json/items/magazine/308.json @@ -86980,7 +87222,7 @@ msgstr "一个30发钢制盒式弹匣,可用于FN SCAR-H步枪。它看上去 #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "FN SCAR-H magazine" msgid_plural "FN SCAR-H magazines" -msgstr[0] "" +msgstr[0] "FN SCAR-H 步枪弹匣" #. ~ Description for {'str': 'FN SCAR-H magazine'} #: data/json/items/magazine/308.json @@ -86991,7 +87233,7 @@ msgstr "一個由軍方配給的 20 發鋼製盒狀彈匣, 適用於 FN SCAR-H #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "FN SCAR-H makeshift magazine" msgid_plural "FN SCAR-H makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 FN SCAR-H 步枪弹匣" #. ~ Description for {'str': 'FN SCAR-H makeshift magazine'} #: data/json/items/magazine/308.json @@ -87038,7 +87280,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "AR-10 magazine" msgid_plural "AR-10 magazines" -msgstr[0] "" +msgstr[0] "AR-10 步枪弹匣" #. ~ Description for {'str': 'AR-10 magazine'} #: data/json/items/magazine/308.json @@ -87049,7 +87291,7 @@ msgstr "一個 20 發裝雙夾盒式彈匣,適用於 AR-10 步槍。" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "AR-10 makeshift magazine" msgid_plural "AR-10 makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 AR-10 步枪弹匣" #. ~ Description for {'str': 'AR-10 makeshift magazine'} #: data/json/items/magazine/308.json @@ -87062,7 +87304,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/json/items/magazine/32.json msgid "Walther PPK magazine" msgid_plural "Walther PPK magazines" -msgstr[0] "" +msgstr[0] "瓦尔特 PPK 手枪弹匣" #. ~ Description for {'str': 'Walther PPK magazine'} #: data/json/items/magazine/32.json @@ -87072,7 +87314,7 @@ msgstr "一個標準的 8 發鋼製盒狀彈匣, 適用於瓦爾特 PPK 手槍 #: data/json/items/magazine/32.json msgid "SIG P230 magazine" msgid_plural "SIG P230 magazines" -msgstr[0] "" +msgstr[0] "西格&绍尔P230手枪弹匣" #. ~ Description for {'str': 'SIG P230 magazine'} #: data/json/items/magazine/32.json @@ -87082,7 +87324,7 @@ msgstr "一個工廠規格的 8 發彈匣, 適用於 SIG 紹爾 P230 手槍。" #: data/json/items/magazine/32.json msgid "Skorpion Vz. 61 magazine" msgid_plural "Skorpion Vz. 61 magazines" -msgstr[0] "" +msgstr[0] "Skorpion Vz. 61 \"蝎\"式微冲弹匣" #. ~ Description for {'str': 'Skorpion Vz. 61 magazine'} #: data/json/items/magazine/32.json @@ -87092,7 +87334,7 @@ msgstr "一個標準的 20 發鋼製盒狀彈匣, 能容納 .32 ACP 子彈, 適 #: data/json/items/magazine/32.json msgid "Kel-Tec P32 magazine" msgid_plural "Kel-Tec P32 magazines" -msgstr[0] "" +msgstr[0] "Kel-Tec P32 手枪弹匣" #. ~ Description for {'str': 'Kel-Tec P32 magazine'} #: data/json/items/magazine/32.json @@ -87102,7 +87344,7 @@ msgstr "一個標準的 7 發裝鋼製盒式彈匣,適用於 Kel-Tec P32 手 #: data/json/items/magazine/357sig.json msgid "P226 .357 SIG magazine" msgid_plural "P226 .357 SIG magazines" -msgstr[0] "" +msgstr[0] "P226 .357 西格手枪弹匣" #. ~ Description for {'str': 'P226 .357 SIG magazine'} #: data/json/items/magazine/357sig.json @@ -87114,7 +87356,7 @@ msgstr "一个12发双排盒式弹匣,用于使用.357 西格弹的西格&绍 #: data/json/items/magazine/357sig.json msgid "P320 .357 SIG magazine" msgid_plural "P320 .357 SIG magazines" -msgstr[0] "" +msgstr[0] "P320 .357 西格手枪弹匣" #. ~ Description for {'str': 'P320 .357 SIG magazine'} #: data/json/items/magazine/357sig.json @@ -87124,7 +87366,7 @@ msgstr "为西格&绍尔 P320 手枪设计的13发双排盒式弹匣。" #: data/json/items/magazine/38.json msgid ".38/.357 7-round speedloader" msgid_plural ".38/.357 7-round speedloaders" -msgstr[0] "" +msgstr[0] "7发快速装弹器 (.38/.357)" #. ~ Description for {'str': '.38/.357 7-round speedloader'} #: data/json/items/magazine/38.json @@ -87136,7 +87378,7 @@ msgstr "這個快速裝填器可以容納7發.357麥格農子彈或.38特殊彈 #: data/json/items/magazine/38.json msgid ".38/.357 5-round speedloader" msgid_plural ".38/.357 5-round speedloaders" -msgstr[0] "" +msgstr[0] "5发快速装弹器 (.38/.357)" #. ~ Description for {'str': '.38/.357 5-round speedloader'} #: data/json/items/magazine/38.json @@ -87148,7 +87390,7 @@ msgstr "這個快速裝填器可以容納5發.357麥格農子彈或.38特殊彈 #: data/json/items/magazine/38.json msgid ".38/.357 6-round speedloader" msgid_plural ".38/.357 6-round speedloaders" -msgstr[0] "" +msgstr[0] "6发快速装弹器 (.38/.357)" #. ~ Description for {'str': '.38/.357 6-round speedloader'} #: data/json/items/magazine/38.json @@ -87160,7 +87402,7 @@ msgstr "这个快速装弹器可以装载 6 发 .357 马格南弹或 .38 特装 #: data/json/items/magazine/380.json msgid "Kel-Tec P3AT magazine" msgid_plural "Kel-Tec P3AT magazines" -msgstr[0] "" +msgstr[0] "Kel-Tec P3AT 手枪弹匣" #. ~ Description for {'str': 'Kel-Tec P3AT magazine'} #: data/json/items/magazine/380.json @@ -87170,7 +87412,7 @@ msgstr "一个标准的6发钢制盒式弹匣,可用于Kel-Tec P3AT 手枪。" #: data/json/items/magazine/380.json msgid "FN 1910 magazine" msgid_plural "FN 1910 magazines" -msgstr[0] "" +msgstr[0] "FN 1910 手枪弹匣" #. ~ Description for {'str': 'FN 1910 magazine'} #: data/json/items/magazine/380.json @@ -87181,7 +87423,7 @@ msgstr "一个标准的6发钢制盒式弹匣,可用于FN 1910手枪。这个 #: data/json/items/magazine/380.json msgid "Ruger LCP magazine" msgid_plural "Ruger LCP magazines" -msgstr[0] "" +msgstr[0] "鲁格 LCP 手枪弹匣" #. ~ Description for {'str': 'Ruger LCP magazine'} #: data/json/items/magazine/380.json @@ -87191,7 +87433,7 @@ msgstr "一个标准的6发容量弹匣,可用于鲁格 LCP 手枪。" #: data/json/items/magazine/380.json msgid "MAC-11 magazine" msgid_plural "MAC-11 magazines" -msgstr[0] "" +msgstr[0] "MAC-11 冲锋枪弹匣" #. ~ Description for {'str': 'MAC-11 magazine'} #: data/json/items/magazine/380.json @@ -87201,7 +87443,7 @@ msgstr "一个标准的32发钢制盒式弹匣,可用于MAC-11冲锋枪。" #: data/json/items/magazine/380.json msgid "CF-380 8-round magazine" msgid_plural "CF-380 8-round magazines" -msgstr[0] "" +msgstr[0] "CF-380 8发弹匣" #. ~ Description for {'str': 'CF-380 8-round magazine'} #: data/json/items/magazine/380.json @@ -87211,7 +87453,7 @@ msgstr "一个 8 发钢制盒式弹匣,可用于 Hi-Point CF-380 手枪。" #: data/json/items/magazine/380.json msgid "CF-380 10-round magazine" msgid_plural "CF-380 10-round magazines" -msgstr[0] "" +msgstr[0] "CF-380 10发弹匣" #. ~ Description for {'str': 'CF-380 10-round magazine'} #: data/json/items/magazine/380.json @@ -87221,7 +87463,7 @@ msgstr "一个 10 发钢制盒式弹匣,可用于 Hi-Point CF-380 手枪。" #: data/json/items/magazine/380.json msgid "Taurus Spectrum magazine" msgid_plural "Taurus Spectrum magazines" -msgstr[0] "" +msgstr[0] "陶鲁斯\"光谱\"手枪弹匣" #. ~ Description for {'str': 'Taurus Spectrum magazine'} #: data/json/items/magazine/380.json @@ -87232,7 +87474,7 @@ msgstr "一个紧凑的钢制盒式弹匣,可用于陶鲁斯\"光谱\"手枪 #: data/json/items/magazine/38super.json msgid "AF2011A1 magazine" msgid_plural "AF2011A1 magazines" -msgstr[0] "" +msgstr[0] "AF2011A1弹匣" #. ~ Description for {'str': 'AF2011A1 magazine'} #: data/json/items/magazine/38super.json @@ -87244,7 +87486,7 @@ msgstr "两个 .38 超级弹8发盒式弹匣被连接在同一个基座上,总 #: data/json/items/magazine/38super.json msgid "M1911 .38 Super magazine" msgid_plural "M1911 .38 Super magazines" -msgstr[0] "" +msgstr[0] "M1911 .38超级弹匣" #. ~ Description for {'str': 'M1911 .38 Super magazine'} #: data/json/items/magazine/38super.json @@ -87254,7 +87496,7 @@ msgstr "一个紧凑的M1911单排盒式弹匣。" #: data/json/items/magazine/40.json msgid ".40 6-round speedloader" msgid_plural ".40 6-round speedloaders" -msgstr[0] "" +msgstr[0] "6发快速装弹器(.40口径)" #. ~ Description for {'str': '.40 6-round speedloader'} #: data/json/items/magazine/40.json @@ -87266,7 +87508,7 @@ msgstr "這個快速裝填器可以容納6發.40 S&W或10mm Auto子彈並快速 #: data/json/items/magazine/40.json msgid "90two .40 S&W magazine" msgid_plural "90two .40 S&W magazines" -msgstr[0] "" +msgstr[0] "90TWO .40 S&W 手枪弹匣" #. ~ Description for {'str': '90two .40 S&W magazine'} #: data/json/items/magazine/40.json @@ -87278,7 +87520,7 @@ msgstr "伯莱塔92和96系列手枪所使用的弹匣,能装填12发 .40 S&W #: data/json/items/magazine/40.json msgid "Glock 22 extended magazine" msgid_plural "Glock 22 extended magazines" -msgstr[0] "" +msgstr[0] "格洛克 22 手枪扩充弹匣" #. ~ Description for {'str': 'Glock 22 extended magazine'} #: data/json/items/magazine/40.json @@ -87290,7 +87532,7 @@ msgstr "加长的22发弹匣,用于格洛克手枪,可装填 .40 S&W弹 或 #: data/json/items/magazine/40.json msgid "Glock 22 magazine" msgid_plural "Glock 22 magazines" -msgstr[0] "" +msgstr[0] "格洛克 22 手枪弹匣" #. ~ Description for {'str': 'Glock 22 magazine'} #: data/json/items/magazine/40.json @@ -87302,7 +87544,7 @@ msgstr "一个紧凑且重量轻的高分子聚合物弹匣,用于格洛克手 #: data/json/items/magazine/40.json msgid "Px4 .40 magazine" msgid_plural "Px4 .40 magazines" -msgstr[0] "" +msgstr[0] "Px4 .40 手枪弹匣" #. ~ Description for {'str': 'Px4 .40 magazine'} #: data/json/items/magazine/40.json @@ -87313,7 +87555,7 @@ msgstr "伯莱塔 Px4 \"风暴\"手枪所使用的弹匣,能装填14发 .40 S& #: data/json/items/magazine/40.json msgid "SIG Pro .40 magazine" msgid_plural "SIG Pro .40 magazines" -msgstr[0] "" +msgstr[0] "西格&绍尔Pro .40手枪弹匣" #. ~ Description for {'str': 'SIG Pro .40 magazine'} #: data/json/items/magazine/40.json @@ -87323,7 +87565,7 @@ msgstr "一個簡潔可靠的彈匣, 適用於 SIG Pro .40 手槍。" #: data/json/items/magazine/40.json msgid "makeshift .40 20-round magazine" msgid_plural "makeshift .40 20-round magazines" -msgstr[0] "" +msgstr[0] "自制 .40 20 弹匣" #. ~ Description for {'str': 'makeshift .40 20-round magazine'} #: data/json/items/magazine/40.json @@ -87336,7 +87578,7 @@ msgstr "一个自制弹匣,基本上与自制Luty冲锋枪兼容,只是供 #: data/json/items/magazine/40.json msgid "Hi-Power .40 S&W magazine" msgid_plural "Hi-Power .40 S&W magazines" -msgstr[0] "" +msgstr[0] "勃朗宁大威力 .40 S&W 手枪弹匣" #. ~ Description for {'str': 'Hi-Power .40 S&W magazine'} #: data/json/items/magazine/40.json @@ -87346,7 +87588,7 @@ msgstr "一个 10 发钢制盒式弹匣,可用于勃朗宁大威力 .40 S&W #: data/json/items/magazine/40.json msgid "PPQ .40 S&W 10-round magazine" msgid_plural "PPQ .40 S&W 10-round magazines" -msgstr[0] "" +msgstr[0] "PPQ .40 S&W 10发弹匣" #. ~ Description for {'str': 'PPQ .40 S&W 10-round magazine'} #: data/json/items/magazine/40.json @@ -87356,7 +87598,7 @@ msgstr "一个 10 发钢制盒式弹匣,可用于瓦尔特 PPQ .40 S&W 手枪 #: data/json/items/magazine/40.json msgid "PPQ .40 S&W 12-round magazine" msgid_plural "PPQ .40 S&W 12-round magazines" -msgstr[0] "" +msgstr[0] "PPQ .40 S&W 12发弹匣" #. ~ Description for {'str': 'PPQ .40 S&W 12-round magazine'} #: data/json/items/magazine/40.json @@ -87366,7 +87608,7 @@ msgstr "一个 12 发钢制盒式弹匣,可用于瓦尔特 PPQ .40 S&W 手枪 #: data/json/items/magazine/40.json msgid "PPQ .40 S&W 14-round magazine" msgid_plural "PPQ .40 S&W 14-round magazines" -msgstr[0] "" +msgstr[0] "PPQ .40 S&W 14发弹匣" #. ~ Description for {'str': 'PPQ .40 S&W 14-round magazine'} #: data/json/items/magazine/40.json @@ -87376,7 +87618,7 @@ msgstr "一个 14 发钢制盒式弹匣,可用于瓦尔特 PPQ .40 S&W 手枪 #: data/json/items/magazine/40.json msgid "Model JCP magazine" msgid_plural "Model JCP magazines" -msgstr[0] "" +msgstr[0] "Hi-Point JCP 型手枪弹匣" #. ~ Description for {'str': 'Model JCP magazine'} #: data/json/items/magazine/40.json @@ -87387,7 +87629,7 @@ msgstr "一个 10 发钢制盒式弹匣,可用于 Hi-Point JCP 型手枪。" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "grenade belt" msgid_plural "grenade belts" -msgstr[0] "" +msgstr[0] "榴弹带" #. ~ Description for {'str': 'grenade belt'} #: data/json/items/magazine/40mm.json @@ -87400,7 +87642,7 @@ msgstr "一條彈鏈。子彈間有著金屬鏈結, 會在發射後解體。這 #: data/json/items/magazine/410shot.json msgid "Saiga-410 box magazine" msgid_plural "Saiga-410 box magazines" -msgstr[0] "" +msgstr[0] "Saiga-410霰弹枪盒式弹匣" #. ~ Description for {'str': 'Saiga-410 box magazine'} #: data/json/items/magazine/410shot.json @@ -87412,7 +87654,7 @@ msgstr "一个可拆卸塑料盒式弹匣,可用于Saiga-410霰弹枪。容量 #: data/json/items/magazine/410shot.json msgid "Saiga-410 drum magazine" msgid_plural "Saiga-410 drum magazines" -msgstr[0] "" +msgstr[0] "Saiga-410霰弹枪鼓式弹匣" #. ~ Description for {'str': 'Saiga-410 drum magazine'} #: data/json/items/magazine/410shot.json @@ -87424,7 +87666,7 @@ msgstr "一个可拆卸塑料弹鼓,可用于Saiga-410霰弹枪。容量为30 #: data/json/items/magazine/44.json msgid ".44 6-round speedloader" msgid_plural ".44 6-round speedloaders" -msgstr[0] "" +msgstr[0] "6发快速装弹器(.44口径)" #. ~ Description for {'str': '.44 6-round speedloader'} #: data/json/items/magazine/44.json @@ -87436,7 +87678,7 @@ msgstr "這個快速裝填器可以容納6發.44子彈並快速重新裝填相 #: data/json/items/magazine/44.json msgid "Desert Eagle magazine" msgid_plural "Desert Eagle magazines" -msgstr[0] "" +msgstr[0] "沙漠之鹰 弹匣" #. ~ Description for {'str': 'Desert Eagle magazine'} #: data/json/items/magazine/44.json @@ -87447,7 +87689,7 @@ msgstr "一個標準的 7 發鋼製盒狀彈匣, 適用於以色列軍工的沙 #: data/json/items/magazine/45.json msgid "MAC-10 magazine" msgid_plural "MAC-10 magazines" -msgstr[0] "" +msgstr[0] "MAC-10 冲锋枪弹匣" #. ~ Description for {'str': 'MAC-10 magazine'} #: data/json/items/magazine/45.json @@ -87457,7 +87699,7 @@ msgstr "一個便宜的 30 發鋼製盒狀彈匣, 適用於 MAC-10 衝鋒槍。" #: data/json/items/magazine/45.json msgid "MAC-10 makeshift magazine" msgid_plural "MAC-10 makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 MAC-10 冲锋枪弹匣" #. ~ Description for {'str': 'MAC-10 makeshift magazine'} #: data/json/items/magazine/45.json @@ -87470,7 +87712,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/json/items/magazine/45.json msgid "TDI Vector magazine" msgid_plural "TDI Vector magazines" -msgstr[0] "" +msgstr[0] "TDI 维克托冲锋枪弹匣" #. ~ Description for {'str': 'TDI Vector magazine'} #: data/json/items/magazine/45.json @@ -87480,7 +87722,7 @@ msgstr "一個 30 發鋼製盒狀彈匣, 適用於 TDI Vector 衝鋒槍。" #: data/json/items/magazine/45.json msgid "Thompson extended magazine" msgid_plural "Thompson extended magazines" -msgstr[0] "" +msgstr[0] "汤普森冲锋枪扩充弹匣" #. ~ Description for {'str': 'Thompson extended magazine'} #: data/json/items/magazine/45.json @@ -87490,7 +87732,7 @@ msgstr "一個加長型 30 發彈匣, 適用於湯普森衝鋒槍。" #: data/json/items/magazine/45.json msgid "Thompson drum magazine" msgid_plural "Thompson drum magazines" -msgstr[0] "" +msgstr[0] "汤普森冲锋枪弹鼓" #. ~ Description for {'str': 'Thompson drum magazine'} #: data/json/items/magazine/45.json @@ -87503,7 +87745,7 @@ msgstr "一個 50 發彈鼓, 適用於湯普森衝鋒槍, 因黑幫而臭名昭 #: data/json/items/magazine/45.json msgid "Thompson magazine" msgid_plural "Thompson magazines" -msgstr[0] "" +msgstr[0] "汤普森冲锋枪弹匣" #. ~ Description for {'str': 'Thompson magazine'} #: data/json/items/magazine/45.json @@ -87513,7 +87755,7 @@ msgstr "一個標準的 20 發彈匣, 適用於湯普森衝鋒槍。" #: data/json/items/magazine/45.json msgid "Thompson makeshift magazine" msgid_plural "Thompson makeshift magazines" -msgstr[0] "" +msgstr[0] "自制汤普森冲锋枪弹匣" #. ~ Description for {'str': 'Thompson makeshift magazine'} #: data/json/items/magazine/45.json @@ -87526,7 +87768,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/json/items/magazine/45.json msgid "UMP45 magazine" msgid_plural "UMP45 magazines" -msgstr[0] "" +msgstr[0] "UMP45冲锋枪弹匣" #. ~ Description for {'str': 'UMP45 magazine'} #: data/json/items/magazine/45.json @@ -87536,7 +87778,7 @@ msgstr "一个标准的25发弹匣,可用于H&K UMP45冲锋枪。" #: data/json/items/magazine/45.json msgid "UMP45 makeshift magazine" msgid_plural "UMP45 makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 UMP45 冲锋枪弹匣" #. ~ Description for {'str': 'UMP45 makeshift magazine'} #: data/json/items/magazine/45.json @@ -87549,7 +87791,7 @@ msgstr "一个简易的单排盒式弹匣,被强力胶带勉强粘起来的, #: data/json/items/magazine/45.json msgid "USP .45 magazine" msgid_plural "USP .45 magazines" -msgstr[0] "" +msgstr[0] "USP .45手枪弹匣" #. ~ Description for {'str': 'USP .45 magazine'} #: data/json/items/magazine/45.json @@ -87559,7 +87801,7 @@ msgstr "一個標準容量的彈匣, 適用於 H&K USP 手槍。" #: data/json/items/magazine/45.json msgid "PPQ .45 ACP magazine" msgid_plural "PPQ .45 ACP magazines" -msgstr[0] "" +msgstr[0] "PPQ .45 ACP 手枪弹匣" #. ~ Description for {'str': 'PPQ .45 ACP magazine'} #: data/json/items/magazine/45.json @@ -87569,7 +87811,7 @@ msgstr "一个 12 发钢制盒式弹匣,可用于瓦尔特 PPQ .45 ACP 手枪 #: data/json/items/magazine/45.json msgid "Model JHP magazine" msgid_plural "Model JHP magazines" -msgstr[0] "" +msgstr[0] "Hi-Point JHP 型手枪弹匣" #. ~ Description for {'str': 'Model JHP magazine'} #: data/json/items/magazine/45.json @@ -87579,7 +87821,7 @@ msgstr "一个 9 发钢制盒式弹匣,可用于 Hi-Point JHP 型手枪。" #: data/json/items/magazine/45.json msgid "Glock 21 13-round magazine" msgid_plural "Glock 21 13-round magazines" -msgstr[0] "" +msgstr[0] "格洛克 21 13发弹匣" #. ~ Description for {'str': 'Glock 21 13-round magazine'} #: data/json/items/magazine/45.json @@ -87589,7 +87831,7 @@ msgstr "一个标准容量的弹匣,可用于格洛克 21 手枪。" #: data/json/items/magazine/45.json msgid "Glock 21 26-round magazine" msgid_plural "Glock 21 26-round magazines" -msgstr[0] "" +msgstr[0] "格洛克 21 26发弹匣" #. ~ Description for {'str': 'Glock 21 26-round magazine'} #: data/json/items/magazine/45.json @@ -87599,7 +87841,7 @@ msgstr "一个双倍容量的弹匣,可用于格洛克 21 手枪。" #: data/json/items/magazine/454.json msgid ".454 5-round speedloader" msgid_plural ".454 5-round speedloaders" -msgstr[0] "" +msgstr[0] "5发快速装弹器(.454口径)" #. ~ Description for {'str': '.454 5-round speedloader'} #. ~ Description for {'str': '.454 6-round speedloader'} @@ -87612,12 +87854,12 @@ msgstr "这种快速装弹器能装载5发.454或.45口径子弹及.410口径霰 #: data/json/items/magazine/454.json msgid ".454 6-round speedloader" msgid_plural ".454 6-round speedloaders" -msgstr[0] "" +msgstr[0] "6发快速装弹器(.454口径)" #: data/json/items/magazine/46.json msgid "H&K 4.6mm extended magazine" msgid_plural "H&K 4.6mm extended magazines" -msgstr[0] "" +msgstr[0] "H&K 4.6mm 扩充弹匣" #. ~ Description for {'str': 'H&K 4.6mm extended magazine'} #: data/json/items/magazine/46.json @@ -87628,7 +87870,7 @@ msgstr "一個加長型 40 發彈匣, 適用於 H&K 專屬的 4.6x30mm 子彈。 #: data/json/items/magazine/46.json msgid "H&K 4.6mm magazine" msgid_plural "H&K 4.6mm magazines" -msgstr[0] "" +msgstr[0] "H&K 4.6mm 弹匣" #. ~ Description for {'str': 'H&K 4.6mm magazine'} #: data/json/items/magazine/46.json @@ -87640,7 +87882,7 @@ msgstr "一個標準的 20 發彈匣, 適用於 H&K 專屬的 4.6x30mm 子彈。 #: data/json/items/magazine/460.json msgid "M1911 extended magazine" msgid_plural "M1911 extended magazines" -msgstr[0] "" +msgstr[0] "M1911 手枪扩充弹匣" #. ~ Description for {'str': 'M1911 extended magazine'} #: data/json/items/magazine/460.json @@ -87650,7 +87892,7 @@ msgstr "一個加長型 10 發彈匣, 適用於 M1911 手槍。" #: data/json/items/magazine/460.json msgid "M1911 magazine" msgid_plural "M1911 magazines" -msgstr[0] "" +msgstr[0] "M1911 手枪弹匣" #. ~ Description for {'str': 'M1911 magazine'} #: data/json/items/magazine/460.json @@ -87660,12 +87902,12 @@ msgstr "一個由軍方配給的 7 發彈匣, 適用於 M1911 手槍。" #: data/json/items/magazine/50.json msgid ".50 BMG ammo belt" msgid_plural ".50 BMG ammo belts" -msgstr[0] "" +msgstr[0] ".50 BMG 子弹带" #: data/json/items/magazine/50.json msgid "Barrett magazine" msgid_plural "Barrett magazines" -msgstr[0] "" +msgstr[0] "巴雷特M107A1 弹匣" #. ~ Description for {'str': 'Barrett magazine'} #: data/json/items/magazine/50.json @@ -87676,7 +87918,7 @@ msgstr "一個標準的 10 發盒狀彈匣, 適用於巴雷特 M107A1 反器材 #: data/json/items/magazine/50.json msgid "AS50 magazine" msgid_plural "AS50 magazines" -msgstr[0] "" +msgstr[0] "AS50 步枪弹匣" #. ~ Description for {'str': 'AS50 magazine'} #: data/json/items/magazine/50.json @@ -87686,7 +87928,7 @@ msgstr "一个 10 发盒式弹匣,可用于精密国际公司出品的 AS50 #: data/json/items/magazine/50.json msgid "TAC-50 magazine" msgid_plural "TAC-50 magazines" -msgstr[0] "" +msgstr[0] "TAC-50 步枪弹匣" #. ~ Description for {'str': 'TAC-50 magazine'} #: data/json/items/magazine/50.json @@ -87696,7 +87938,7 @@ msgstr "一个 5 发盒式弹匣,可用于麦克米兰公司出品的 TAC-50 #: data/json/items/magazine/500.json msgid ".500 5-round speedloader" msgid_plural ".500 5-round speedloaders" -msgstr[0] "" +msgstr[0] "5发快速装弹器(.500口径)" #. ~ Description for {'str': '.500 5-round speedloader'} #: data/json/items/magazine/500.json @@ -87708,7 +87950,7 @@ msgstr "這個快速裝填器可以容納5發.500子彈並快速重新裝填相 #: data/json/items/magazine/545x39.json msgid "AK-74M magazine" msgid_plural "AK-74M magazines" -msgstr[0] "" +msgstr[0] "AK-74M步枪弹匣" #. ~ Description for {'str': 'AK-74M magazine'} #: data/json/items/magazine/545x39.json @@ -87720,7 +87962,7 @@ msgstr "一個標準的 AK-74M 步槍彈匣, 以鋼強化聚合物製成。能 #: data/json/items/magazine/545x39.json msgid "AK-74M extended magazine" msgid_plural "AK-74M extended magazines" -msgstr[0] "" +msgstr[0] "AK-74M步枪扩充弹匣" #. ~ Description for {'str': 'AK-74M extended magazine'} #: data/json/items/magazine/545x39.json @@ -87732,7 +87974,7 @@ msgstr "一個 45 發的彈匣。設計上是用於 RPK-74 輕型機關槍, 但 #: data/json/items/magazine/57.json msgid "FN-57 magazine" msgid_plural "FN-57 magazines" -msgstr[0] "" +msgstr[0] "FN-57手枪弹匣" #. ~ Description for {'str': 'FN-57 magazine'} #: data/json/items/magazine/57.json @@ -87742,7 +87984,7 @@ msgstr "一個標準容量彈匣, 適用於 FN Five-Seven 手槍。" #: data/json/items/magazine/57.json msgid "FN-P90 magazine" msgid_plural "FN-P90 magazines" -msgstr[0] "" +msgstr[0] "FN-P90冲锋枪弹匣" #. ~ Description for {'str': 'FN-P90 magazine'} #: data/json/items/magazine/57.json @@ -87754,7 +87996,7 @@ msgstr "一個半透明的盒型聚合物彈匣, 由工廠生產。適用於 FN #: data/json/items/magazine/5x50.json msgid "RMFB100 5x50mm extended magazine" msgid_plural "RMFB100 5x50mm extended magazines" -msgstr[0] "" +msgstr[0] "RMFB100 5x50mm 扩充弹匣" #. ~ Description for {'str': 'RMFB100 5x50mm extended magazine'} #: data/json/items/magazine/5x50.json @@ -87764,7 +88006,7 @@ msgstr "一個 100 發的盒型彈匣, 適用於 5x50mm 鋼鏢彈。" #: data/json/items/magazine/5x50.json msgid "RMFB50 5x50mm magazine" msgid_plural "RMFB50 5x50mm magazines" -msgstr[0] "" +msgstr[0] "RMFB50 5x50mm 弹匣" #. ~ Description for {'str': 'RMFB50 5x50mm magazine'} #: data/json/items/magazine/5x50.json @@ -87774,7 +88016,7 @@ msgstr "一個 50 發的盒型彈匣, 適用於 5x50mm 鋼鏢彈。" #: data/json/items/magazine/66mm.json msgid "M74 rocket clip" msgid_plural "M74 rocket clips" -msgstr[0] "" +msgstr[0] "M74 火箭弹弹夹" #. ~ Description for {'str': 'M74 rocket clip'} #: data/json/items/magazine/66mm.json @@ -87785,12 +88027,12 @@ msgstr "M202A1 肩射式火焰進攻武器使用的火箭彈匣,能裝填 4 #: data/json/items/magazine/762.json msgid "7.62x39mm clip" msgid_plural "7.62x39mm clips" -msgstr[0] "" +msgstr[0] "7.62x39mm 弹夹" #: data/json/items/magazine/762.json msgid "AK 10-round magazine" msgid_plural "AK 10-round magazines" -msgstr[0] "" +msgstr[0] "AK 10发弹匣" #. ~ Description for {'str': 'AK 10-round magazine'} #: data/json/items/magazine/762.json @@ -87802,7 +88044,7 @@ msgstr "紧凑型10发弹匣,可用于7.62x39 AK型步枪,由冲压金属板 #: data/json/items/magazine/762.json msgid "AK 20-round magazine" msgid_plural "AK 20-round magazines" -msgstr[0] "" +msgstr[0] "AK 20发弹匣" #. ~ Description for {'str': 'AK 20-round magazine'} #: data/json/items/magazine/762.json @@ -87814,7 +88056,7 @@ msgstr "紧凑型20发弹匣,可用于7.62x39 AK型步枪,由冲压金属板 #: data/json/items/magazine/762.json msgid "AK 30-round magazine" msgid_plural "AK 30-round magazines" -msgstr[0] "" +msgstr[0] "AK 30发弹匣" #. ~ Description for {'str': 'AK 30-round magazine'} #: data/json/items/magazine/762.json @@ -87826,7 +88068,7 @@ msgstr "紧凑型30发弹匣,可用于7.62x39 AK型步枪,由冲压金属板 #: data/json/items/magazine/762.json msgid "AK 40-round magazine" msgid_plural "AK 40-round magazines" -msgstr[0] "" +msgstr[0] "AK 40发弹匣" #. ~ Description for {'str': 'AK 40-round magazine'} #: data/json/items/magazine/762.json @@ -87838,7 +88080,7 @@ msgstr "加长型40发弹匣,可用于7.62x39 AK型步枪,由冲压金属板 #: data/json/items/magazine/762.json msgid "AK 75-round drum magazine" msgid_plural "AK 75-round drum magazines" -msgstr[0] "" +msgstr[0] "AK 75发弹鼓" #. ~ Description for {'str': 'AK 75-round drum magazine'} #: data/json/items/magazine/762.json @@ -87850,12 +88092,12 @@ msgstr "笨重的75发弹鼓,可用于7.62x39 AK型步枪,由冲压金属板 #: data/json/items/magazine/762R.json msgid "7.62x54mmR clip" msgid_plural "7.62x54mmR clips" -msgstr[0] "" +msgstr[0] "7.62x54mmR 弹夹" #: data/json/items/magazine/762x25.json msgid "PPSh 71-round drum magazine" msgid_plural "PPSh 71-round drum magazines" -msgstr[0] "" +msgstr[0] "PPSh 71发弹鼓" #. ~ Description for {'str': 'PPSh 71-round drum magazine'} #: data/json/items/magazine/762x25.json @@ -87865,7 +88107,7 @@ msgstr "PPSh-41 適用的高容量彈鼓。" #: data/json/items/magazine/762x25.json msgid "PPSh 35-round magazine" msgid_plural "PPSh 35-round magazines" -msgstr[0] "" +msgstr[0] "PPSh 35发弹匣" #. ~ Description for {'str': 'PPSh 35-round magazine'} #: data/json/items/magazine/762x25.json @@ -87875,7 +88117,7 @@ msgstr "一個 35 發盒狀彈匣, 適用於 PPSh-41。" #: data/json/items/magazine/762x25.json msgid "Tokarev TT-33 magazine" msgid_plural "Tokarev TT-33 magazines" -msgstr[0] "" +msgstr[0] "托卡列夫TT-33手枪弹匣" #. ~ Description for {'str': 'Tokarev TT-33 magazine'} #: data/json/items/magazine/762x25.json @@ -87885,7 +88127,7 @@ msgstr "標準的 8 發彈匣, 適用於托卡列夫 TT-33。" #: data/json/items/magazine/8x40mm.json msgid "RMGB100 8x40mm magazine" msgid_plural "RMGB100 8x40mm magazines" -msgstr[0] "" +msgstr[0] "RMGB100 8x40mm 弹匣" #. ~ Description for {'str': 'RMGB100 8x40mm magazine'} #: data/json/items/magazine/8x40mm.json @@ -87896,7 +88138,7 @@ msgstr "一個 100 發的盒型彈匣, 適用於 Rivtech 8x40mm 無殼彈。" #: data/json/items/magazine/8x40mm.json msgid "RMGP10 8x40mm stick magazine" msgid_plural "RMGP10 8x40mm stick magazines" -msgstr[0] "" +msgstr[0] "RMGP10 8x40mm 条形弹匣" #. ~ Description for {'str': 'RMGP10 8x40mm stick magazine'} #: data/json/items/magazine/8x40mm.json @@ -87907,7 +88149,7 @@ msgstr "一個 10 發的條狀彈匣, 適用於 Rivtech 8x40mm 無殼彈。" #: data/json/items/magazine/8x40mm.json msgid "RMGD250 8x40mm drum magazine" msgid_plural "RMGD250 8x40mm drum magazines" -msgstr[0] "" +msgstr[0] "RMGD250 8x40mm 弹鼓" #. ~ Description for {'str': 'RMGD250 8x40mm drum magazine'} #: data/json/items/magazine/8x40mm.json @@ -87918,7 +88160,7 @@ msgstr "一個 250 發的彈鼓, 適用於 Rivtech 8x40mm 無殼彈。" #: data/json/items/magazine/8x40mm.json msgid "RMGP25 8x40mm stick magazine" msgid_plural "RMGP25 8x40mm stick magazines" -msgstr[0] "" +msgstr[0] "RMGP25 8x40mm 条形弹匣" #. ~ Description for {'str': 'RMGP25 8x40mm stick magazine'} #: data/json/items/magazine/8x40mm.json @@ -87929,7 +88171,7 @@ msgstr "一個 25 發的條狀彈匣, 適用於 Rivtech 8x40mm 無殼彈。" #: data/json/items/magazine/8x40mm.json msgid "RMGB500 8x40mm drum magazine" msgid_plural "RMGB500 8x40mm drum magazines" -msgstr[0] "" +msgstr[0] "RMGD500 8x40mm 弹鼓" #. ~ Description for {'str': 'RMGB500 8x40mm drum magazine'} #: data/json/items/magazine/8x40mm.json @@ -87940,7 +88182,7 @@ msgstr "一個 500 發的彈鼓, 適用於 Rivtech 8x40mm 無殼彈。" #: data/json/items/magazine/8x40mm.json msgid "RMGB50 8x40mm magazine" msgid_plural "RMGB50 8x40mm magazines" -msgstr[0] "" +msgstr[0] "RMGB50 8x40mm 弹匣" #. ~ Description for {'str': 'RMGB50 8x40mm magazine'} #: data/json/items/magazine/8x40mm.json @@ -87950,7 +88192,7 @@ msgstr "一個 50 發的盒型彈匣, 適用於 Rivtech 8x40mm 無殼彈。" #: data/json/items/magazine/8x40mm.json data/mods/No_Hope/Items/magazines.json msgid "RMGS5 8x40mm speedloader" msgid_plural "RMGS5 8x40mm speedloaders" -msgstr[0] "" +msgstr[0] "RMGS5 快速装弹器(8x40mm口径)" #. ~ Description for {'str': 'RMGS5 8x40mm speedloader'} #: data/json/items/magazine/8x40mm.json data/mods/No_Hope/Items/magazines.json @@ -87962,7 +88204,7 @@ msgstr "這款由Rivtech 製造,針對RM99 左輪手槍設計的快速裝填 #: data/json/items/magazine/9mm.json msgid "Calico magazine" msgid_plural "Calico magazines" -msgstr[0] "" +msgstr[0] "卡利科M960冲锋枪弹匣" #. ~ Description for {'str': 'Calico magazine'} #: data/json/items/magazine/9mm.json @@ -87974,7 +88216,7 @@ msgstr "一個 50 發的螺旋彈筒, 出乎意料地簡潔可靠。適用於卡 #: data/json/items/magazine/9mm.json msgid "Glock extended magazine" msgid_plural "Glock extended magazines" -msgstr[0] "" +msgstr[0] "格洛克手枪扩充弹匣" #. ~ Description for {'str': 'Glock extended magazine'} #: data/json/items/magazine/9mm.json @@ -87986,7 +88228,7 @@ msgstr "一個加長型 30 發聚合物彈匣, 適用於格洛克系列槍械。 #: data/json/items/magazine/9mm.json msgid "Glock magazine" msgid_plural "Glock magazines" -msgstr[0] "" +msgstr[0] "格洛克手枪弹匣" #. ~ Description for {'str': 'Glock magazine'} #: data/json/items/magazine/9mm.json @@ -87998,7 +88240,7 @@ msgstr "一個簡潔輕巧的聚合物彈匣, 適用於格洛克系列槍械。" #: data/json/items/magazine/9mm.json msgid "Glock 17 17-round magazine" msgid_plural "Glock 17 17-round magazines" -msgstr[0] "" +msgstr[0] "格洛克17发弹匣" #. ~ Description for {'str': 'Glock 17 17-round magazine'} #: data/json/items/magazine/9mm.json @@ -88008,7 +88250,7 @@ msgstr "為格洛克17而製作, 這個彈匣能填裝17發子彈。" #: data/json/items/magazine/9mm.json msgid "Glock 17 22-round magazine" msgid_plural "Glock 17 22-round magazines" -msgstr[0] "" +msgstr[0] "格洛克22发弹匣" #. ~ Description for {'str': 'Glock 17 22-round magazine'} #: data/json/items/magazine/9mm.json @@ -88018,7 +88260,7 @@ msgstr "為格洛克17而製作, 這個彈匣能填裝22發子彈。" #: data/json/items/magazine/9mm.json msgid "Glock 50-round drum magazine" msgid_plural "Glock 50-round drum magazines" -msgstr[0] "" +msgstr[0] "格洛克50发弹鼓" #. ~ Description for {'str': 'Glock 50-round drum magazine'} #: data/json/items/magazine/9mm.json @@ -88028,7 +88270,7 @@ msgstr "為格洛克手槍而製作, 這個彈匣能填裝50發子彈。" #: data/json/items/magazine/9mm.json msgid "Glock 100-round drum magazine" msgid_plural "Glock 100-round drum magazines" -msgstr[0] "" +msgstr[0] "格洛克100发弹鼓" #. ~ Description for {'str': 'Glock 100-round drum magazine'} #: data/json/items/magazine/9mm.json @@ -88038,7 +88280,7 @@ msgstr "為格洛克手槍而製作, 這個彈鼓能填裝100發子彈。" #: data/json/items/magazine/9mm.json msgid "M9 extended magazine" msgid_plural "M9 extended magazines" -msgstr[0] "" +msgstr[0] "M9手枪扩充弹匣" #. ~ Description for {'str': 'M9 extended magazine'} #: data/json/items/magazine/9mm.json @@ -88050,7 +88292,7 @@ msgstr "30发扩充弹匣,可用于M9手枪的同时也和某些现代卡宾 #: data/json/items/magazine/9mm.json msgid "M9 magazine" msgid_plural "M9 magazines" -msgstr[0] "" +msgstr[0] "M9手枪弹匣" #. ~ Description for {'str': 'M9 magazine'} #: data/json/items/magazine/9mm.json @@ -88062,7 +88304,7 @@ msgstr "一個由軍方配給的 15 發盒狀彈匣, 原先是供貝瑞塔 M9 #: data/json/items/magazine/9mm.json msgid "MP5 extended magazine" msgid_plural "MP5 extended magazines" -msgstr[0] "" +msgstr[0] "MP5冲锋枪扩充弹匣" #. ~ Description for {'str': 'MP5 extended magazine'} #: data/json/items/magazine/9mm.json @@ -88074,7 +88316,7 @@ msgstr "一个弹鼓,可用于H&K MP5 冲锋枪。相较于工厂生产的标 #: data/json/items/magazine/9mm.json msgid "MP5 magazine" msgid_plural "MP5 magazines" -msgstr[0] "" +msgstr[0] "MP5冲锋枪弹匣" #. ~ Description for {'str': 'MP5 magazine'} #: data/json/items/magazine/9mm.json @@ -88084,7 +88326,7 @@ msgstr "一個標準容量的弧形彈匣, 適用於 H&K MP5 衝鋒槍。" #: data/json/items/magazine/9mm.json msgid "Px4 magazine" msgid_plural "Px4 magazines" -msgstr[0] "" +msgstr[0] "Px4 手枪弹匣" #. ~ Description for {'str': 'Px4 magazine'} #: data/json/items/magazine/9mm.json @@ -88094,7 +88336,7 @@ msgstr "伯莱塔 Px4 \"风暴\"手枪所使用的标准弹匣,装填 9x19mm #: data/json/items/magazine/9mm.json msgid "STEN magazine" msgid_plural "STEN magazines" -msgstr[0] "" +msgstr[0] "斯登冲锋枪弹匣" #. ~ Description for {'str': 'STEN magazine'} #: data/json/items/magazine/9mm.json @@ -88106,7 +88348,7 @@ msgstr "一個雙排裝彈、單發進彈的 9x19mm 彈匣, 適用於斯登衝 #: data/json/items/magazine/9mm.json msgid "makeshift STEN magazine" msgid_plural "makeshift STEN magazines" -msgstr[0] "" +msgstr[0] "自制斯登冲锋枪弹匣" #. ~ Description for {'str': 'makeshift STEN magazine'} #: data/json/items/magazine/9mm.json @@ -88118,7 +88360,7 @@ msgstr "一个自制弹匣,基本上与斯登冲锋枪兼容,只是供弹机 #: data/json/items/magazine/9mm.json msgid "TEC-9 magazine" msgid_plural "TEC-9 magazines" -msgstr[0] "" +msgstr[0] "TEC-9冲锋枪弹匣" #. ~ Description for {'str': 'TEC-9 magazine'} #: data/json/items/magazine/9mm.json @@ -88130,7 +88372,7 @@ msgstr "一個便宜但不太可靠的 32 發鋼製盒狀彈匣, 適用於 TEC-9 #: data/json/items/magazine/9mm.json msgid "USP 9mm magazine" msgid_plural "USP 9mm magazines" -msgstr[0] "" +msgstr[0] "USP 9mm手枪弹匣" #. ~ Description for {'str': 'USP 9mm magazine'} #: data/json/items/magazine/9mm.json @@ -88142,7 +88384,7 @@ msgstr "一個工業規格的 15 發盒狀彈匣,適用於可靠的 H&K USP 9x #: data/json/items/magazine/9mm.json msgid "UZI magazine" msgid_plural "UZI magazines" -msgstr[0] "" +msgstr[0] "UZI冲锋枪弹匣" #. ~ Description for {'str': 'UZI magazine'} #: data/json/items/magazine/9mm.json @@ -88152,7 +88394,7 @@ msgstr "一個標準的 32 發鋼製盒狀彈匣, 適用於 UZI 衝鋒槍。" #: data/json/items/magazine/9mm.json msgid "Kel-Tec PF-9 magazine" msgid_plural "Kel-Tec PF-9 magazines" -msgstr[0] "" +msgstr[0] "Kel Tec PF-9手枪弹匣" #. ~ Description for {'str': 'Kel-Tec PF-9 magazine'} #: data/json/items/magazine/9mm.json @@ -88162,7 +88404,7 @@ msgstr "一个标准的7发钢制盒式弹匣,可用于Kel-Tec PF-9手枪。" #: data/json/items/magazine/9mm.json msgid "P320 9x19mm magazine" msgid_plural "P320 9x19mm magazines" -msgstr[0] "" +msgstr[0] "P320 9x19mm 手枪弹匣" #. ~ Description for {'str': 'P320 9x19mm magazine'} #: data/json/items/magazine/9mm.json @@ -88172,7 +88414,7 @@ msgstr "为西格&绍尔 P320 手枪设计的17发双排盒式弹匣。" #: data/json/items/magazine/9mm.json msgid "Hi-Power 9x19mm 13-round magazine" msgid_plural "Hi-Power 9x19mm 13-round magazines" -msgstr[0] "" +msgstr[0] "勃朗宁大威力 9x19mm 13发弹匣" #. ~ Description for {'str': 'Hi-Power 9x19mm 13-round magazine'} #: data/json/items/magazine/9mm.json @@ -88182,7 +88424,7 @@ msgstr "一个 13 发钢制盒式弹匣,可用于勃朗宁大威力 9x19mm 手 #: data/json/items/magazine/9mm.json msgid "Hi-Power 9x19mm 15-round magazine" msgid_plural "Hi-Power 9x19mm 15-round magazines" -msgstr[0] "" +msgstr[0] "勃朗宁大威力 9x19mm 15发弹匣" #. ~ Description for {'str': 'Hi-Power 9x19mm 15-round magazine'} #: data/json/items/magazine/9mm.json @@ -88192,7 +88434,7 @@ msgstr "一个 15 发钢制盒式弹匣,可用于勃朗宁大威力 9x19mm 手 #: data/json/items/magazine/9mm.json msgid "P38 magazine" msgid_plural "P38 magazines" -msgstr[0] "" +msgstr[0] "瓦尔特 P38 手枪弹匣" #. ~ Description for {'str': 'P38 magazine'} #: data/json/items/magazine/9mm.json @@ -88202,7 +88444,7 @@ msgstr "一个 8 发钢制盒式弹匣,可用于瓦尔特 P38 手枪。" #: data/json/items/magazine/9mm.json msgid "PPQ 9x19mm 10-round magazine" msgid_plural "PPQ 9x19mm 10-round magazines" -msgstr[0] "" +msgstr[0] "PPQ 9x19mm 10发弹匣" #. ~ Description for {'str': 'PPQ 9x19mm 10-round magazine'} #: data/json/items/magazine/9mm.json @@ -88212,7 +88454,7 @@ msgstr "一个 10 发钢制盒式弹匣,可用于瓦尔特 PPQ 9mm 手枪。" #: data/json/items/magazine/9mm.json msgid "PPQ 9x19mm 15-round magazine" msgid_plural "PPQ 9x19mm 15-round magazines" -msgstr[0] "" +msgstr[0] "PPQ 9x19mm 15发弹匣" #. ~ Description for {'str': 'PPQ 9x19mm 15-round magazine'} #: data/json/items/magazine/9mm.json @@ -88222,7 +88464,7 @@ msgstr "一个 15 发钢制盒式弹匣,可用于瓦尔特 PPQ 9mm 手枪。" #: data/json/items/magazine/9mm.json msgid "PPQ 9x19mm 17-round magazine" msgid_plural "PPQ 9x19mm 17-round magazines" -msgstr[0] "" +msgstr[0] "PPQ 9x19mm 17发弹匣" #. ~ Description for {'str': 'PPQ 9x19mm 17-round magazine'} #: data/json/items/magazine/9mm.json @@ -88232,7 +88474,7 @@ msgstr "一个 17 发钢制盒式弹匣,可用于瓦尔特 PPQ 9mm 手枪。" #: data/json/items/magazine/9mm.json msgid "C-9 8-round magazine" msgid_plural "C-9 8-round magazines" -msgstr[0] "" +msgstr[0] "C-9 8发弹匣" #. ~ Description for {'str': 'C-9 8-round magazine'} #: data/json/items/magazine/9mm.json @@ -88242,7 +88484,7 @@ msgstr "一个 8 发钢制盒式弹匣,可用于 Hi-Point C-9 手枪。" #: data/json/items/magazine/9mm.json msgid "C-9 10-round magazine" msgid_plural "C-9 10-round magazines" -msgstr[0] "" +msgstr[0] "C-9 10发弹匣" #. ~ Description for {'str': 'C-9 10-round magazine'} #: data/json/items/magazine/9mm.json @@ -88252,7 +88494,7 @@ msgstr "一个 10 发钢制盒式弹匣,可用于 Hi-Point C-9 手枪。" #: data/json/items/magazine/9mm.json msgid "C-9 15-round magazine" msgid_plural "C-9 15-round magazines" -msgstr[0] "" +msgstr[0] "C-9 15发弹匣" #. ~ Description for {'str': 'C-9 15-round magazine'} #: data/json/items/magazine/9mm.json @@ -88262,7 +88504,7 @@ msgstr "一个 15 发钢制盒式弹匣,可用于 Hi-Point C-9 手枪。" #: data/json/items/magazine/9mm.json msgid "CZ 75 12-round magazine" msgid_plural "CZ 75 12-round magazines" -msgstr[0] "" +msgstr[0] "CZ-75 12发弹匣" #. ~ Description for {'str': 'CZ 75 12-round magazine'} #: data/json/items/magazine/9mm.json @@ -88272,7 +88514,7 @@ msgstr "一个 12 发钢制盒式弹匣,可用于 CZ-75 手枪。" #: data/json/items/magazine/9mm.json msgid "CZ 75 20-round magazine" msgid_plural "CZ 75 20-round magazines" -msgstr[0] "" +msgstr[0] "CZ-75 20发弹匣" #. ~ Description for {'str': 'CZ 75 20-round magazine'} #: data/json/items/magazine/9mm.json @@ -88282,7 +88524,7 @@ msgstr "一个 20 发钢制盒式弹匣,可用于 CZ-75 手枪。" #: data/json/items/magazine/9mm.json msgid "CZ 75 26-round magazine" msgid_plural "CZ 75 26-round magazines" -msgstr[0] "" +msgstr[0] "CZ-75 26发弹匣" #. ~ Description for {'str': 'CZ 75 26-round magazine'} #: data/json/items/magazine/9mm.json @@ -88292,7 +88534,7 @@ msgstr "一个 26 发钢制盒式弹匣,可用于 CZ-75 手枪。" #: data/json/items/magazine/9mm.json msgid "CCP magazine" msgid_plural "CCP magazines" -msgstr[0] "" +msgstr[0] "瓦尔特 CCP 手枪弹匣" #. ~ Description for {'str': 'CCP magazine'} #: data/json/items/magazine/9mm.json @@ -88302,7 +88544,7 @@ msgstr "一个 8 发钢制盒式弹匣,可用于瓦尔特 CCP 手枪。" #: data/json/items/magazine/9x18.json msgid "Makarov PM magazine" msgid_plural "Makarov PM magazines" -msgstr[0] "" +msgstr[0] "马卡洛夫PM手枪弹匣" #. ~ Description for {'str': 'Makarov PM magazine'} #: data/json/items/magazine/9x18.json @@ -88312,7 +88554,7 @@ msgstr "馬卡洛夫手槍的標準彈匣, 能容納 8 發子彈。" #: data/json/items/magazine/9x18.json msgid "Skorpion Vz. 82 magazine" msgid_plural "Skorpion Vz. 82 magazines" -msgstr[0] "" +msgstr[0] "Skorpion Vz. 82 \"蝎\"式微冲弹匣" #. ~ Description for {'str': 'Skorpion Vz. 82 magazine'} #: data/json/items/magazine/9x18.json @@ -88323,7 +88565,7 @@ msgstr "一個標準的 20 發鋼製盒狀彈匣, 能容納 9x18mm 馬卡洛夫 #: data/json/items/magazine/chemical_spray.json msgid "pressurized chemical tank" msgid_plural "pressurized chemical tanks" -msgstr[0] "" +msgstr[0] "加压化学品罐" #. ~ Description for {'str': 'pressurized chemical tank'} #: data/json/items/magazine/chemical_spray.json @@ -88335,7 +88577,7 @@ msgstr "粗製的加壓 2公升鋼瓶,設計用於粗製化學藥劑噴灑器 #: data/json/items/magazine/liquid.json msgid "pressurized fuel tank" msgid_plural "pressurized fuel tanks" -msgstr[0] "" +msgstr[0] "加压油罐" #. ~ Description for {'str': 'pressurized fuel tank'} #: data/json/items/magazine/liquid.json @@ -88345,7 +88587,7 @@ msgstr "一個3公升加壓鋼瓶,設計用於餵養火焰噴射器中的卡 #: data/json/items/magazine/liquid.json msgid "small pressurized fuel tank" msgid_plural "small pressurized fuel tanks" -msgstr[0] "" +msgstr[0] "小型加压油罐" #. ~ Description for {'str': 'small pressurized fuel tank'} #: data/json/items/magazine/liquid.json @@ -88357,7 +88599,7 @@ msgstr "這是一個0.5L加壓鋼瓶,適用於槍管下掛式小型火焰噴 #: data/json/items/magazine/liquid.json msgid "RM450-2 fuel canister" msgid_plural "RM450-2 fuel canisters" -msgstr[0] "" +msgstr[0] "RM450-2 燃料罐" #. ~ Description for {'str': 'RM450-2 fuel canister'} #: data/json/items/magazine/liquid.json @@ -88369,7 +88611,7 @@ msgstr "一個2公升加壓鋼瓶,附有閥門,設計用於餵養RM451火焰 #: data/json/items/magazine/liquid.json msgid "RM450-4 fuel canister" msgid_plural "RM450-4 fuel canisters" -msgstr[0] "" +msgstr[0] "RM450-4 燃料罐" #. ~ Description for {'str': 'RM450-4 fuel canister'} #: data/json/items/magazine/liquid.json @@ -88381,7 +88623,7 @@ msgstr "一個4公升加壓鋼瓶,附有閥門,設計用於餵養RM451火焰 #: data/json/items/magazine/shot.json msgid "Saiga-12 box magazine" msgid_plural "Saiga-12 box magazines" -msgstr[0] "" +msgstr[0] "Saiga-12霰弹枪盒式弹匣" #. ~ Description for {'str': 'Saiga-12 box magazine'} #: data/json/items/magazine/shot.json @@ -88392,7 +88634,7 @@ msgstr "一個可移除的塑料彈匣, 適用於 Saiga-12 霰彈槍, 能容納 #: data/json/items/magazine/shot.json msgid "Saiga-12 drum magazine" msgid_plural "Saiga-12 drum magazines" -msgstr[0] "" +msgstr[0] "Saiga-12霰弹枪鼓式弹匣" #. ~ Description for {'str': 'Saiga-12 drum magazine'} #: data/json/items/magazine/shot.json @@ -88403,7 +88645,7 @@ msgstr "一個可移除的塑料彈鼓, 適用於 Saiga-12 霰彈槍, 能容納 #: data/json/items/magazine/shot.json msgid "USAS-12 box magazine" msgid_plural "USAS-12 box magazines" -msgstr[0] "" +msgstr[0] "USAS-12 霰弹枪盒式弹匣" #. ~ Description for {'str': 'USAS-12 box magazine'} #: data/json/items/magazine/shot.json @@ -88414,7 +88656,7 @@ msgstr "一个可拆卸塑料弹匣,可用于 USAS-12 霰弹枪。容量为10 #: data/json/items/magazine/shot.json msgid "USAS-12 drum magazine" msgid_plural "USAS-12 drum magazines" -msgstr[0] "" +msgstr[0] "USAS-12 霰弹枪弹鼓" #. ~ Description for {'str': 'USAS-12 drum magazine'} #: data/json/items/magazine/shot.json @@ -88425,7 +88667,7 @@ msgstr "一个可拆卸塑料弹匣,可用于 USAS-12 霰弹枪。容量为20 #: data/json/items/magazine/shot.json msgid "shotshell belt" msgid_plural "shotshell belts" -msgstr[0] "" +msgstr[0] "霰弹弹链" #. ~ Description for {'str': 'shotshell belt'} #: data/json/items/magazine/shot.json @@ -88437,7 +88679,7 @@ msgstr "不可散式布制弹链,可容纳20发霰弹。明显不如金属弹 #: data/json/items/magazine/shot.json msgid "shotgun 6-round tube speedloader" msgid_plural "shotgun 6-round tube speedloaders" -msgstr[0] "" +msgstr[0] "6发管状快速装弹器(霰弹)" #. ~ Description for {'str': 'shotgun 6-round tube speedloader'} #: data/json/items/magazine/shot.json @@ -88450,7 +88692,7 @@ msgstr "一根带滑动手柄的塑料管,能够比手工装填更快地将 6 #: data/json/items/magazine/shot.json msgid "shotgun 8-round tube speedloader" msgid_plural "shotgun 8-round tube speedloaders" -msgstr[0] "" +msgstr[0] "8发管状快速装弹器(霰弹)" #. ~ Description for {'str': 'shotgun 8-round tube speedloader'} #: data/json/items/magazine/shot.json @@ -88463,7 +88705,7 @@ msgstr "一根带滑动手柄的塑料管,能够比手工装填更快地将 8 #: data/json/items/magazine/weldgas.json msgid "small welding tank" msgid_plural "small welding tanks" -msgstr[0] "" +msgstr[0] "小型焊接气瓶" #. ~ Description for {'str': 'small welding tank'} #: data/json/items/magazine/weldgas.json @@ -88475,7 +88717,7 @@ msgstr "一個裝載高壓焊接氣體的小鋼瓶。上面標有幾個褪色無 #: data/json/items/magazine/weldgas.json msgid "welding tank" msgid_plural "welding tanks" -msgstr[0] "" +msgstr[0] "焊接气瓶" #. ~ Description for {'str': 'welding tank'} #: data/json/items/magazine/weldgas.json @@ -88500,7 +88742,7 @@ msgstr "這是一把巨大的戰斧。雖然只建議作為武器使用, 但也 #: data/json/items/melee/axes.json msgid "battle axe replica" msgid_plural "battle axe replicas" -msgstr[0] "" +msgstr[0] "战斧(复制品)" #. ~ Description for {'str': 'battle axe replica'} #: data/json/items/melee/axes.json @@ -88512,7 +88754,7 @@ msgstr "這是一把巨大的戰斧。你注意到斧頭的位置不太正確。 #: data/json/items/melee/axes.json msgid "battle axe fake" msgid_plural "battle axe fakes" -msgstr[0] "" +msgstr[0] "战斧(赝品)" #. ~ Description for {'str': 'battle axe fake'} #: data/json/items/melee/axes.json @@ -88535,7 +88777,7 @@ msgstr "這是把多功能的長柄武器, 長棍上有著斧刃、尖刺和其 #: data/json/items/melee/axes.json msgid "halberd fake" msgid_plural "halberd fakes" -msgstr[0] "" +msgstr[0] "战戟(赝品)" #. ~ Description for {'str': 'halberd fake'} #: data/json/items/melee/axes.json @@ -88607,7 +88849,7 @@ msgstr "一根鋁製的球棒, 比木製球棒更輕更好揮。" #: data/json/items/melee/bludgeons.json msgid "foam rubber bat" msgid_plural "foam rubber bats" -msgstr[0] "" +msgstr[0] "泡沫橡胶球棒" #. ~ Description for {'str': 'foam rubber bat'} #: data/json/items/melee/bludgeons.json @@ -88719,7 +88961,7 @@ msgstr "這是一把不論在重量或平衡上都準確地用真品為範本、 #: data/json/items/melee/bludgeons.json msgid "bokken replica" msgid_plural "bokken replicas" -msgstr[0] "" +msgstr[0] "木刀(复制品)" #. ~ Description for {'str': 'bokken replica'} #: data/json/items/melee/bludgeons.json @@ -88731,7 +88973,7 @@ msgstr "一柄用于锻炼的木刀,但看上去像是批量生产的便宜货 #: data/json/items/melee/bludgeons.json msgid "bokken fake" msgid_plural "bokken fakes" -msgstr[0] "" +msgstr[0] "木刀(赝品)" #. ~ Description for {'str': 'bokken fake'} #: data/json/items/melee/bludgeons.json @@ -88765,7 +89007,7 @@ msgstr "無論你肢體有沒有殘缺, 你總是可以用一根手杖讓你走 #: data/json/items/melee/bludgeons.json msgid "hollow cane" msgid_plural "hollow canes" -msgstr[0] "" +msgstr[0] "空心手杖" #. ~ Description for {'str': 'hollow cane'} #: data/json/items/melee/bludgeons.json @@ -88814,7 +89056,7 @@ msgstr "一支大而沈重的鎚子。對非常強壯的人這是一把還可以 #: data/json/items/melee/bludgeons.json msgid "short sledge hammer" msgid_plural "short sledge hammers" -msgstr[0] "" +msgstr[0] "短钢锤" #. ~ Description for {'str': 'short sledge hammer'} #: data/json/items/melee/bludgeons.json @@ -88826,7 +89068,7 @@ msgstr "一把较短的钢锤,由于使用和大钢锤相同的钢制锤头, #: data/json/items/melee/bludgeons.json msgid "heavy sledge hammer" msgid_plural "heavy sledge hammers" -msgstr[0] "" +msgstr[0] "重钢锤" #. ~ Description for {'str': 'heavy sledge hammer'} #: data/json/items/melee/bludgeons.json @@ -88838,7 +89080,7 @@ msgstr "一把巨大的钢锤,有着一个同样巨大而沉重的锤头。这 #: data/json/items/melee/bludgeons.json msgid "engineer's hammer" msgid_plural "engineer's hammers" -msgstr[0] "" +msgstr[0] "工程师锤" #. ~ Description for {'str': "engineer's hammer"} #: data/json/items/melee/bludgeons.json @@ -88938,7 +89180,7 @@ msgstr "这种多功能的长柄武器上面有一个钉锤头,一个矛头, #: data/json/items/melee/bludgeons.json msgid "lucerne hammer fake" msgid_plural "lucerne hammer fakes" -msgstr[0] "" +msgstr[0] "琉森锤(赝品)" #. ~ Description for {'str': 'lucerne hammer fake'} #: data/json/items/melee/bludgeons.json @@ -88962,7 +89204,7 @@ msgstr "一件中世紀武器, 由一個木頭握柄與末端沉重的鐵塊組 #: data/json/items/melee/bludgeons.json msgid "mace replica" msgid_plural "mace replicas" -msgstr[0] "" +msgstr[0] "钉头槌(复制品)" #. ~ Description for {'str': 'mace replica'} #: data/json/items/melee/bludgeons.json @@ -88974,7 +89216,7 @@ msgstr "一件鐵製的中世紀木頭手柄武器。鐵頭端感覺有些虛浮 #: data/json/items/melee/bludgeons.json msgid "mace fake" msgid_plural "mace fakes" -msgstr[0] "" +msgstr[0] "钉头槌(赝品)" #. ~ Description for {'str': 'mace fake'} #: data/json/items/melee/bludgeons.json @@ -88999,7 +89241,7 @@ msgstr "这是一个简易皮革短槌,由两片皮革之间夹上配重制成 #: data/json/items/melee/bludgeons.json msgid "Mjoelnir" msgid_plural "Mjoelnirs" -msgstr[0] "" +msgstr[0] "雷神之锤" #. ~ Description for {'str': 'Mjoelnir'} #: data/json/items/melee/bludgeons.json @@ -89034,7 +89276,7 @@ msgstr "一件中世紀武器, 由一個木頭握柄與末端沉重的鐵刺球 #: data/json/items/melee/bludgeons.json msgid "morningstar replica" msgid_plural "morningstar replicas" -msgstr[0] "" +msgstr[0] "晨星锤(复制品)" #. ~ Description for {'str': 'morningstar replica'} #: data/json/items/melee/bludgeons.json @@ -89046,7 +89288,7 @@ msgstr "一件鐵製的中世紀木頭手柄武器。鐵頭端感覺過輕了。 #: data/json/items/melee/bludgeons.json msgid "morningstar fake" msgid_plural "morningstar fakes" -msgstr[0] "" +msgstr[0] "晨星锤(赝品)" #. ~ Description for {'str': 'morningstar fake'} #: data/json/items/melee/bludgeons.json @@ -89213,7 +89455,7 @@ msgstr "一个挖空的木棍,内部填充了铅或其他易熔金属,使其 #: data/json/items/melee/bludgeons.json msgid "shillelagh fake" msgid_plural "shillelagh fakes" -msgstr[0] "" +msgstr[0] "爱尔兰木槌(赝品)" #. ~ Description for {'str': 'shillelagh fake'} #: data/json/items/melee/bludgeons.json @@ -89322,7 +89564,7 @@ msgstr "由最先端科技所打造約一尺的合金刀刃, 它的刀鋒是號 #: data/json/items/melee/knives_kitchen.json msgid "generic kitchen knife" msgid_plural "generic kitchen knives" -msgstr[0] "" +msgstr[0] "通用菜刀" #: data/json/items/melee/knives_kitchen.json msgid "butcher knife" @@ -89445,7 +89687,7 @@ msgstr "" #: data/json/items/melee/misc.json msgid "scourge" msgid_plural "scourges" -msgstr[0] "" +msgstr[0] "九尾鞭" #. ~ Description for {'str': 'scourge'} #: data/json/items/melee/misc.json @@ -89482,7 +89724,7 @@ msgstr "將玻璃碎片的一端裹起, 因此可以更加安全地揮舞。" #: data/json/items/melee/misc.json data/json/obsoletion/items.json msgid "plastic shank" msgid_plural "plastic shanks" -msgstr[0] "" +msgstr[0] "塑料匕首" #. ~ Description for {'str': 'plastic shank'} #: data/json/items/melee/misc.json data/json/obsoletion/items.json @@ -89731,7 +89973,7 @@ msgstr "一把結實的長柄武器, 有著彎曲的刀身, 使用的製作手 #: data/json/items/melee/spears_and_polearms.json msgid "naginata replica" msgid_plural "naginata replicas" -msgstr[0] "" +msgstr[0] "薙刀(复制品)" #. ~ Description for {'str': 'naginata replica'} #: data/json/items/melee/spears_and_polearms.json @@ -89744,7 +89986,7 @@ msgstr "一把坚硬的带弯曲刀刃的长柄刀,用与武士刀和其他日 #: data/json/items/melee/spears_and_polearms.json msgid "naginata fake" msgid_plural "naginata fakes" -msgstr[0] "" +msgstr[0] "薙刀(复制品)" #. ~ Description for {'str': 'naginata fake'} #: data/json/items/melee/spears_and_polearms.json @@ -89794,7 +90036,7 @@ msgstr "一根有鐵槍頭的木製標槍。握把做了防滑的蝕刻。" msgctxt "weapon" msgid "wooden pike" msgid_plural "wooden pikes" -msgstr[0] "" +msgstr[0] "木制重矛" #. ~ Description for {'ctxt': 'weapon', 'str': 'wooden pike'} #: data/json/items/melee/spears_and_polearms.json @@ -89807,7 +90049,7 @@ msgstr "一把中世纪武器,由木杆枪身与用火烤硬的矛尖结合而 msgctxt "weapon" msgid "copper pike" msgid_plural "copper pikes" -msgstr[0] "" +msgstr[0] "铜制重矛" #. ~ Description for {'ctxt': 'weapon', 'str': 'copper pike'} #: data/json/items/melee/spears_and_polearms.json @@ -89833,7 +90075,7 @@ msgstr "一把中世纪武器,由木杆枪身与铁制矛尖结合而成。" msgctxt "weapon" msgid "pike replica" msgid_plural "pike replicas" -msgstr[0] "" +msgstr[0] "重矛(复制品)" #. ~ Description for {'ctxt': 'weapon', 'str': 'pike replica'} #: data/json/items/melee/spears_and_polearms.json @@ -89847,7 +90089,7 @@ msgstr "一把中世纪武器,由木杆枪身与铁制矛尖结合而成。这 msgctxt "weapon" msgid "pike fake" msgid_plural "pike fakes" -msgstr[0] "" +msgstr[0] "重矛(赝品)" #. ~ Description for {'ctxt': 'weapon', 'str': 'pike fake'} #: data/json/items/melee/spears_and_polearms.json @@ -89920,7 +90162,7 @@ msgstr "一些廢鐵條被很粗糙的硬加在原本的木劍上, 所增加的 #: data/json/items/melee/swords_and_blades.json msgid "hand-forged sword" msgid_plural "hand-forged swords" -msgstr[0] "" +msgstr[0] "手锻剑" #. ~ Description for {'str': 'hand-forged sword'} #: data/json/items/melee/swords_and_blades.json @@ -89971,7 +90213,7 @@ msgstr "一把軍用戰鬥刀。非常輕又銳利, 在熟練的人手上相當 #: data/json/items/melee/swords_and_blades.json msgid "modified combat knife" msgid_plural "modified combat knives" -msgstr[0] "" +msgstr[0] "改装战术匕首" #. ~ Description for {'str': 'modified combat knife', 'str_pl': 'modified #. combat knives'} @@ -90066,7 +90308,7 @@ msgstr "把一些尖銳的長棘緊緊地包裹塊破布當做握柄的小刀。 #: data/json/items/melee/swords_and_blades.json msgid "bone shiv" msgid_plural "bone shivs" -msgstr[0] "" +msgstr[0] "骨片刀" #. ~ Description for {'str': 'bone shiv'} #: data/json/items/melee/swords_and_blades.json @@ -90114,7 +90356,7 @@ msgstr "這是一把大刀刃, 握把是用大力膠帶纏的。讓它可以被 #: data/json/items/melee/swords_and_blades.json msgid "machete multitool" msgid_plural "machete multitools" -msgstr[0] "" +msgstr[0] "多功能砍刀" #. ~ Description for {'str': 'machete multitool'} #: data/json/items/melee/swords_and_blades.json @@ -90138,7 +90380,7 @@ msgstr "這是一把近世騎兵使用的彎刀。輕量但是致命的砍劈武 #: data/json/items/melee/swords_and_blades.json msgid "cavalry saber fake" msgid_plural "cavalry saber fakes" -msgstr[0] "" +msgstr[0] "骑兵刀(赝品)" #. ~ Description for {'str': 'cavalry saber fake'} #: data/json/items/melee/swords_and_blades.json @@ -90162,7 +90404,7 @@ msgstr "這把趴浪狀的匕首來自東南亞, 這種刀鋒的設計可以產 #: data/json/items/melee/swords_and_blades.json msgid "kris fake" msgid_plural "kris fakes" -msgstr[0] "" +msgstr[0] "蛇剑(赝品)" #. ~ Description for {'str': 'kris fake'} #: data/json/items/melee/swords_and_blades.json @@ -90200,7 +90442,7 @@ msgstr "一把古中国剑,双刃开锋,剑身长直,护手带有装饰, #: data/json/items/melee/swords_and_blades.json msgid "jian replica" msgid_plural "jian replica" -msgstr[0] "" +msgstr[0] "剑(复制品)" #. ~ Description for {'str_sp': 'jian replica'} #: data/json/items/melee/swords_and_blades.json @@ -90212,7 +90454,7 @@ msgstr "一把古中國劍, 雙刃開鋒, 劍身長直。這把劍頗為破舊, #: data/json/items/melee/swords_and_blades.json msgid "jian fake" msgid_plural "jian fake" -msgstr[0] "" +msgstr[0] "剑(赝品)" #. ~ Description for {'str_sp': 'jian fake'} #: data/json/items/melee/swords_and_blades.json @@ -90237,7 +90479,7 @@ msgstr "這把彎刀與不少中東及中亞國家有著關聯。專為劈砍而 #: data/json/items/melee/swords_and_blades.json msgid "scimitar replica" msgid_plural "scimitar replicas" -msgstr[0] "" +msgstr[0] "弯刀(复制品)" #. ~ Description for {'str': 'scimitar replica'} #: data/json/items/melee/swords_and_blades.json @@ -90249,7 +90491,7 @@ msgstr "這把彎刀與不少中東及中亞國家有著關聯。這把看起來 #: data/json/items/melee/swords_and_blades.json msgid "scimitar fake" msgid_plural "scimitar fakes" -msgstr[0] "" +msgstr[0] "弯刀(赝品)" #. ~ Description for {'str': 'scimitar fake'} #: data/json/items/melee/swords_and_blades.json @@ -90274,7 +90516,7 @@ msgstr "这是一把细长、无锋的刺击用剑,是西洋迅捷剑的前身 #: data/json/items/melee/swords_and_blades.json msgid "estoc replica" msgid_plural "estoc replicas" -msgstr[0] "" +msgstr[0] "穿甲刺剑(复制品)" #. ~ Description for {'str': 'estoc replica'} #: data/json/items/melee/swords_and_blades.json @@ -90287,7 +90529,7 @@ msgstr "这是一把细长、无刃的刺击用剑,是西洋迅捷剑的前身 #: data/json/items/melee/swords_and_blades.json msgid "estoc fake" msgid_plural "estoc fakes" -msgstr[0] "" +msgstr[0] "穿甲刺剑(赝品)" #. ~ Description for {'str': 'estoc fake'} #: data/json/items/melee/swords_and_blades.json @@ -90313,7 +90555,7 @@ msgstr "這是一把經典的中世紀長劍, 體積介乎於騎士劍和後期 #: data/json/items/melee/swords_and_blades.json msgid "longsword replica" msgid_plural "longsword replicas" -msgstr[0] "" +msgstr[0] "长剑(复制品)" #. ~ Description for {'str': 'longsword replica'} #: data/json/items/melee/swords_and_blades.json @@ -90326,7 +90568,7 @@ msgstr "這是一把經典的中世紀長劍, 體積介乎於騎士劍和後期 #: data/json/items/melee/swords_and_blades.json msgid "longsword fake" msgid_plural "longsword fakes" -msgstr[0] "" +msgstr[0] "长剑(赝品)" #. ~ Description for {'str': 'longsword fake'} #: data/json/items/melee/swords_and_blades.json @@ -90349,7 +90591,7 @@ msgstr "這是一把經典的中世紀劍, 適合單手使用。" #: data/json/items/melee/swords_and_blades.json msgid "arming sword replica" msgid_plural "arming sword replicas" -msgstr[0] "" +msgstr[0] "骑士剑(复制品)" #. ~ Description for {'str': 'arming sword replica'} #: data/json/items/melee/swords_and_blades.json @@ -90361,7 +90603,7 @@ msgstr "這是一把經典的中世紀劍, 適合單手使用。這把看起來 #: data/json/items/melee/swords_and_blades.json msgid "arming sword fake" msgid_plural "arming sword fakes" -msgstr[0] "" +msgstr[0] "骑士剑(赝品)" #. ~ Description for {'str': 'arming sword fake'} #: data/json/items/melee/swords_and_blades.json @@ -90437,7 +90679,7 @@ msgstr "劍刺刀是大型的砍殺武器, 能夠附掛在槍械或十字弓的 #: data/json/items/melee/swords_and_blades.json msgid "modified sword bayonet" msgid_plural "modified sword bayonets" -msgstr[0] "" +msgstr[0] "改装长刺刀" #. ~ Description for {'str': 'modified sword bayonet'} #: data/json/items/melee/swords_and_blades.json @@ -90465,7 +90707,7 @@ msgstr "相對於長日本刀, 在較大把的脇差出現前, 是武士們的 #: data/json/items/melee/swords_and_blades.json msgid "tanto replica" msgid_plural "tanto replicas" -msgstr[0] "" +msgstr[0] "日式短刀(复制品)" #. ~ Description for {'str': 'tanto replica'} #: data/json/items/melee/swords_and_blades.json @@ -90478,7 +90720,7 @@ msgstr "日本短劍,在較大把的脇差出現前, 是武士們的備用 #: data/json/items/melee/swords_and_blades.json msgid "tanto fake" msgid_plural "tanto fakes" -msgstr[0] "" +msgstr[0] "日式短刀(赝品)" #. ~ Description for {'str': 'tanto fake'} #: data/json/items/melee/swords_and_blades.json @@ -90490,7 +90732,7 @@ msgstr "這是一個日本短劍的廉價複製品。通常由武士攜帶作為 #: data/json/items/melee/swords_and_blades.json msgid "wakizashi" msgid_plural "wakizashi" -msgstr[0] "" +msgstr[0] "肋差" #. ~ Description for {'str_sp': 'wakizashi'} #: data/json/items/melee/swords_and_blades.json @@ -90502,7 +90744,7 @@ msgstr "這是一種比較常見的日本短劍。體積更小, 比武士刀輕, #: data/json/items/melee/swords_and_blades.json msgid "wakizashi replica" msgid_plural "wakizashi replicas" -msgstr[0] "" +msgstr[0] "肋差(复制品)" #. ~ Description for {'str': 'wakizashi replica'} #: data/json/items/melee/swords_and_blades.json @@ -90514,7 +90756,7 @@ msgstr "這是一種比較常見的日本短劍。這劍感覺不太好。" #: data/json/items/melee/swords_and_blades.json msgid "wakizashi fake" msgid_plural "wakizashi fakes" -msgstr[0] "" +msgstr[0] "肋差(赝品)" #. ~ Description for {'str': 'wakizashi fake'} #: data/json/items/melee/swords_and_blades.json @@ -90526,7 +90768,7 @@ msgstr "這是一個常見的脅差的廉價複製品, 比武士刀更輕、更 #: data/json/items/melee/swords_and_blades.json msgid "zweihaender" msgid_plural "zweihaenders" -msgstr[0] "" +msgstr[0] "双手巨剑" #. ~ Description for {'str': 'zweihaender'} #: data/json/items/melee/swords_and_blades.json @@ -90536,7 +90778,7 @@ msgstr "一把雙手持的巨劍, 源自於德國。具有真正的衝擊力。" #: data/json/items/melee/swords_and_blades.json msgid "zweihaender replica" msgid_plural "zweihaender replicas" -msgstr[0] "" +msgstr[0] "双手巨剑(复制品)" #. ~ Description for {'str': 'zweihaender replica'} #: data/json/items/melee/swords_and_blades.json @@ -90548,7 +90790,7 @@ msgstr "一把雙手持的巨劍, 源自於德國。你不太確定它是否該 #: data/json/items/melee/swords_and_blades.json msgid "zweihaender fake" msgid_plural "zweihaender fakes" -msgstr[0] "" +msgstr[0] "双手巨剑(赝品)" #. ~ Description for {'str': 'zweihaender fake'} #: data/json/items/melee/swords_and_blades.json @@ -90572,7 +90814,7 @@ msgstr "锡克教徒使用的礼仪匕首, 它十分锋利,也许是一种 #: data/json/items/melee/swords_and_blades.json msgid "kirpan replica" msgid_plural "kirpan replicas" -msgstr[0] "" +msgstr[0] "吉尔班弯刀(复制品)" #. ~ Description for {'str': 'kirpan replica'} #: data/json/items/melee/swords_and_blades.json @@ -90596,7 +90838,7 @@ msgstr "由日本傳來的巨大雙手曲劍。重量卻出乎意料的輕。" #: data/json/items/melee/swords_and_blades.json msgid "nodachi replica" msgid_plural "nodachi replicas" -msgstr[0] "" +msgstr[0] "野太刀(复制品)" #. ~ Description for {'str': 'nodachi replica'} #: data/json/items/melee/swords_and_blades.json @@ -90608,7 +90850,7 @@ msgstr "由日本傳來的巨大雙手曲劍。重量卻出乎意料的輕,但 #: data/json/items/melee/swords_and_blades.json msgid "nodachi fake" msgid_plural "nodachi fakes" -msgstr[0] "" +msgstr[0] "野太刀(赝品)" #. ~ Description for {'str': 'nodachi fake'} #: data/json/items/melee/swords_and_blades.json @@ -90633,7 +90875,7 @@ msgstr "一種用於擊劍運動的武器, 擊劍是所有運動中最高貴的 #: data/json/items/melee/swords_and_blades.json msgid "sharpened foil" msgid_plural "sharpened foils" -msgstr[0] "" +msgstr[0] "磨尖花剑" #. ~ Description for {'str': 'sharpened foil'} #: data/json/items/melee/swords_and_blades.json @@ -90648,7 +90890,7 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "electrified foil" msgid_plural "electrified foils" -msgstr[0] "" +msgstr[0] "电击花剑" #. ~ Description for {'str': 'electrified foil'} #: data/json/items/melee/swords_and_blades.json @@ -90665,7 +90907,7 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "fencing épée" msgid_plural "fencing épées" -msgstr[0] "" +msgstr[0] "击剑重剑" #. ~ Description for {'str': 'fencing épée'} #: data/json/items/melee/swords_and_blades.json @@ -90678,7 +90920,7 @@ msgstr "击剑运动用的武器,很高级。这种剑是各种比赛用剑中 #: data/json/items/melee/swords_and_blades.json msgid "sharpened épée" msgid_plural "sharpened épées" -msgstr[0] "" +msgstr[0] "磨尖重剑" #. ~ Description for {'str': 'sharpened épée'} #: data/json/items/melee/swords_and_blades.json @@ -90693,7 +90935,7 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "electrified épée" msgid_plural "electrified épées" -msgstr[0] "" +msgstr[0] "电击重剑" #. ~ Description for {'str': 'electrified épée'} #: data/json/items/melee/swords_and_blades.json @@ -90722,7 +90964,7 @@ msgstr "击剑运动用的武器,很高级。这把有开锋的佩剑比重剑 #: data/json/items/melee/swords_and_blades.json msgid "sharpened saber" msgid_plural "sharpened sabers" -msgstr[0] "" +msgstr[0] "磨尖佩剑" #. ~ Description for {'str': 'sharpened saber'} #: data/json/items/melee/swords_and_blades.json @@ -90737,7 +90979,7 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "electrified saber" msgid_plural "electrified sabers" -msgstr[0] "" +msgstr[0] "电击佩剑" #. ~ Description for {'str': 'electrified saber'} #: data/json/items/melee/swords_and_blades.json @@ -90754,7 +90996,7 @@ msgstr "" #: data/json/items/melee/swords_and_blades.json msgid "sword cane" msgid_plural "sword canes" -msgstr[0] "" +msgstr[0] "手杖剑" #. ~ Description for {'str': 'sword cane'} #: data/json/items/melee/swords_and_blades.json @@ -90776,7 +91018,7 @@ msgstr "這是一把在 16、17、18 世紀使用的近世刀劍。稱它為 \" #: data/json/items/melee/swords_and_blades.json msgid "broadsword replica" msgid_plural "broadsword replicas" -msgstr[0] "" +msgstr[0] "阔剑(复制品)" #. ~ Description for {'str': 'broadsword replica'} #: data/json/items/melee/swords_and_blades.json @@ -90789,7 +91031,7 @@ msgstr "一把仿 16 , 17, 18 世紀的古劍。這劍的作工很糟糕, 但是 #: data/json/items/melee/swords_and_blades.json msgid "broadsword fake" msgid_plural "broadsword fakes" -msgstr[0] "" +msgstr[0] "阔剑(赝品)" #. ~ Description for {'str': 'broadsword fake'} #: data/json/items/melee/swords_and_blades.json @@ -90815,7 +91057,7 @@ msgstr "這是一把有著華麗護手的細劍。適合紳士與劍客決鬥的 #: data/json/items/melee/swords_and_blades.json msgid "rapier fake" msgid_plural "rapier fakes" -msgstr[0] "" +msgstr[0] "迅捷剑(赝品)" #. ~ Description for {'str': 'rapier fake'} #: data/json/items/melee/swords_and_blades.json @@ -90840,7 +91082,7 @@ msgstr "一把來自日本的稀有刀劍。能夠對沒有防具的目標造成 #: data/json/items/melee/swords_and_blades.json msgid "katana replica" msgid_plural "katana replicas" -msgstr[0] "" +msgstr[0] "武士刀(复制品)" #. ~ Description for {'str': 'katana replica'} #: data/json/items/melee/swords_and_blades.json @@ -90852,7 +91094,7 @@ msgstr "這是從日本來的罕見刀刃, 儘管有著正確的刀鋒與重量, #: data/json/items/melee/swords_and_blades.json msgid "katana fake" msgid_plural "katana fakes" -msgstr[0] "" +msgstr[0] "武士刀(赝品)" #. ~ Description for {'str': 'katana fake'} #: data/json/items/melee/swords_and_blades.json @@ -90949,7 +91191,7 @@ msgstr "這是一把寬闊的軍刀, 因為水手和海盜常用而出名, 它 #: data/json/items/melee/swords_and_blades.json msgid "cutlass replica" msgid_plural "cutlass replicas" -msgstr[0] "" +msgstr[0] "短弯刀(复制品)" #. ~ Description for {'str': 'cutlass replica'} #: data/json/items/melee/swords_and_blades.json @@ -90962,7 +91204,7 @@ msgstr "這是一把寬闊的軍刀, 因為水手和海盜常用而出名。這 #: data/json/items/melee/swords_and_blades.json msgid "cutlass fake" msgid_plural "cutlass fakes" -msgstr[0] "" +msgstr[0] "短弯刀(赝品)" #. ~ Description for {'str': 'cutlass fake'} #: data/json/items/melee/swords_and_blades.json @@ -91188,7 +91430,7 @@ msgstr "一个尖锐的金属棍,手柄上有两个弯曲的尖齿。它主要 #: data/json/items/ranged/archery.json msgid "crude wooden arrow" msgid_plural "crude wooden arrows" -msgstr[0] "" +msgstr[0] "粗木箭" #. ~ Description for {'str': 'crude wooden arrow'} #: data/json/items/ranged/archery.json @@ -91200,7 +91442,7 @@ msgstr "這根粗略磨尖過的木頭箭桿背後有凹槽。射擊後有非常 #: data/json/items/ranged/archery.json msgid "wooden bodkin arrow" msgid_plural "wooden bodkin arrows" -msgstr[0] "" +msgstr[0] "木制锥头箭" #. ~ Description for {'str': 'wooden bodkin arrow'} #: data/json/items/ranged/archery.json @@ -91212,7 +91454,7 @@ msgstr "帶有尖頭的木箭。用於貫穿裝甲。射擊後只有低機率可 #: data/json/items/ranged/archery.json msgid "wooden rubber blunt arrow" msgid_plural "wooden rubber blunt arrows" -msgstr[0] "" +msgstr[0] "钝头木箭" #. ~ Description for {'str': 'wooden rubber blunt arrow'} #: data/json/items/ranged/archery.json @@ -91224,7 +91466,7 @@ msgstr "附有箭羽的木製箭桿,箭頭是鈍狀的橡膠頭。能夠擊暈 #: data/json/items/ranged/archery.json msgid "simple wooden small game arrow" msgid_plural "simple wooden small game arrows" -msgstr[0] "" +msgstr[0] "简易木制狩猎小箭" #. ~ Description for {'str': 'simple wooden small game arrow'} #: data/json/items/ranged/archery.json @@ -91237,7 +91479,7 @@ msgstr "一個簡易帶羽木箭,有個又寬又鈍的箭頭。適合用來狩 #: data/json/items/ranged/archery.json msgid "wooden broadhead arrow" msgid_plural "wooden broadhead arrows" -msgstr[0] "" +msgstr[0] "木制宽刃箭" #. ~ Description for {'str': 'wooden broadhead arrow'} #: data/json/items/ranged/archery.json @@ -91250,7 +91492,7 @@ msgstr "一根附有箭羽的木製箭矢,箭頭呈扁片狀。適用於對目 #: data/json/items/ranged/archery.json msgid "simple fire-hardened arrow" msgid_plural "simple fire-hardened arrows" -msgstr[0] "" +msgstr[0] "简易炭化木箭" #. ~ Description for {'str': 'simple fire-hardened arrow'} #: data/json/items/ranged/archery.json @@ -91262,7 +91504,7 @@ msgstr "一個簡易木箭,前方已經削尖並經過火燒碳化。射擊後 #: data/json/items/ranged/archery.json msgid "wooden small game arrow" msgid_plural "wooden small game arrows" -msgstr[0] "" +msgstr[0] "木制狩猎小箭" #. ~ Description for {'str': 'wooden small game arrow'} #: data/json/items/ranged/archery.json @@ -91275,7 +91517,7 @@ msgstr "一個帶羽木箭,有個鈍的箭頭。適合用來狩獵小動物而 #: data/json/items/ranged/archery.json msgid "makeshift field point arrow" msgid_plural "makeshift field point arrows" -msgstr[0] "" +msgstr[0] "自制锥头箭" #. ~ Description for {'str': 'makeshift field point arrow'} #: data/json/items/ranged/archery.json @@ -91287,7 +91529,7 @@ msgstr "一個簡易木箭,前端以粗製磨尖。射擊後有低機率可以 #: data/json/items/ranged/archery.json msgid "simple metal arrow" msgid_plural "simple metal arrows" -msgstr[0] "" +msgstr[0] "简易金属箭" #. ~ Description for {'str': 'simple metal arrow'} #: data/json/items/ranged/archery.json @@ -91299,7 +91541,7 @@ msgstr "簡易且附有箭羽的鋼製箭桿,箭頭削平而且尖銳。射出 #: data/json/items/ranged/archery.json msgid "aluminum broadhead arrow" msgid_plural "aluminum broadhead arrows" -msgstr[0] "" +msgstr[0] "铝制宽刃箭" #. ~ Description for {'str': 'aluminum broadhead arrow'} #: data/json/items/ranged/archery.json @@ -91311,7 +91553,7 @@ msgstr "附有箭羽的鋁製箭桿,箭頭呈扁片狀。適用於對目標造 #: data/json/items/ranged/archery.json msgid "aluminum field point arrow" msgid_plural "aluminum field point arrows" -msgstr[0] "" +msgstr[0] "铝制锥头箭" #. ~ Description for {'str': 'aluminum field point arrow'} #: data/json/items/ranged/archery.json @@ -91323,7 +91565,7 @@ msgstr "附有箭羽的鋁製箭桿,箭頭呈尖銳狀。適用於貫穿護甲 #: data/json/items/ranged/archery.json msgid "aluminum small game arrow" msgid_plural "aluminum small game arrows" -msgstr[0] "" +msgstr[0] "铝制狩猎小箭" #. ~ Description for {'str': 'aluminum small game arrow'} #: data/json/items/ranged/archery.json @@ -91336,7 +91578,7 @@ msgstr "附有箭羽的鋁製箭桿,箭頭呈鈍頭狀。適用於狩獵小型 #: data/json/items/ranged/archery.json msgid "carbon fiber hunting arrow" msgid_plural "carbon fiber hunting arrows" -msgstr[0] "" +msgstr[0] "碳素狩猎箭" #. ~ Description for {'str': 'carbon fiber hunting arrow'} #: data/json/items/ranged/archery.json @@ -91349,7 +91591,7 @@ msgstr "附有箭羽的碳纖維箭桿,箭頭呈擴張的寬頭狀。對目標 #: data/json/items/ranged/archery.json msgid "explosive arrow" msgid_plural "explosive arrows" -msgstr[0] "" +msgstr[0] "爆炸箭" #. ~ Description for {'str': 'explosive arrow'} #: data/json/items/ranged/archery.json @@ -91375,7 +91617,7 @@ msgstr "這小型的土製炸彈可以裝在箭上, 它會在擊中目標時爆 #: data/json/items/ranged/archery.json msgid "flaming arrow" msgid_plural "flaming arrows" -msgstr[0] "" +msgstr[0] "燃烧箭" #. ~ Description for {'str': 'flaming arrow'} #: data/json/items/ranged/archery.json @@ -91508,7 +91750,7 @@ msgstr "一把体型巨大且威力强大的复合弓,强化后的弓身巨大 #: data/json/items/ranged/crossbows.json msgid "crude wooden bolt" msgid_plural "crude wooden bolts" -msgstr[0] "" +msgstr[0] "粗木弩矢" #. ~ Description for {'str': 'crude wooden bolt'} #: data/json/items/ranged/crossbows.json @@ -91520,7 +91762,7 @@ msgstr "一根粗糙的木製尖頭十字弓弩箭,箭尾有凹槽。射出後 #: data/json/items/ranged/crossbows.json msgid "simple fire-hardened bolt" msgid_plural "simple fire-hardened bolts" -msgstr[0] "" +msgstr[0] "简易炭化木弩矢" #. ~ Description for {'str': 'simple fire-hardened bolt'} #: data/json/items/ranged/crossbows.json @@ -91532,7 +91774,7 @@ msgstr "一根簡易附有箭羽的木製十字弓弩箭,箭頭經火烤硬化 #: data/json/items/ranged/crossbows.json msgid "simple wooden small game bolt" msgid_plural "simple wooden small game bolts" -msgstr[0] "" +msgstr[0] "简易木制狩猎小弩矢" #. ~ Description for {'str': 'simple wooden small game bolt'} #: data/json/items/ranged/crossbows.json @@ -91545,7 +91787,7 @@ msgstr "一根簡易附有箭羽的木製十字弓弩箭,箭頭呈鈍狀。適 #: data/json/items/ranged/crossbows.json msgid "makeshift field point bolt" msgid_plural "makeshift field point bolts" -msgstr[0] "" +msgstr[0] "自制锥头弩矢" #. ~ Description for {'str': 'makeshift field point bolt'} #: data/json/items/ranged/crossbows.json @@ -91557,7 +91799,7 @@ msgstr "一根附有箭羽的十字弓弩箭,有著粗製的箭頭。射出後 #: data/json/items/ranged/crossbows.json msgid "wooden broadhead bolt" msgid_plural "wooden broadhead bolts" -msgstr[0] "" +msgstr[0] "木制宽刃弩矢" #. ~ Description for {'str': 'wooden broadhead bolt'} #: data/json/items/ranged/crossbows.json @@ -91570,7 +91812,7 @@ msgstr "一根附有箭羽的木製十字弓弩箭,箭頭呈扁片狀。適用 #: data/json/items/ranged/crossbows.json msgid "wooden bodkin bolt" msgid_plural "wooden bodkin bolts" -msgstr[0] "" +msgstr[0] "木制锥头弩矢" #. ~ Description for {'str': 'wooden bodkin bolt'} #: data/json/items/ranged/crossbows.json @@ -91582,7 +91824,7 @@ msgstr "一根附有箭羽的木製十字弓弩箭,箭頭呈尖銳狀。適用 #: data/json/items/ranged/crossbows.json msgid "wooden small game bolt" msgid_plural "wooden small game bolts" -msgstr[0] "" +msgstr[0] "木制狩猎小弩矢" #. ~ Description for {'str': 'wooden small game bolt'} #: data/json/items/ranged/crossbows.json @@ -91595,7 +91837,7 @@ msgstr "一根附有箭羽的木製十字弓弩箭,箭頭呈鈍狀。適用於 #: data/json/items/ranged/crossbows.json msgid "simple metal bolt" msgid_plural "simple metal bolts" -msgstr[0] "" +msgstr[0] "简易金属弩矢" #. ~ Description for {'str': 'simple metal bolt'} #: data/json/items/ranged/crossbows.json @@ -91607,7 +91849,7 @@ msgstr "一根附有箭羽的鋼製十字弓弩箭,箭頭削平而且尖銳。 #: data/json/items/ranged/crossbows.json msgid "aluminum broadhead bolt" msgid_plural "aluminum broadhead bolts" -msgstr[0] "" +msgstr[0] "铝制宽刃弩矢" #. ~ Description for {'str': 'aluminum broadhead bolt'} #: data/json/items/ranged/crossbows.json @@ -91619,7 +91861,7 @@ msgstr "帶有寬大尖端的十字弓鋁弩箭。用於最大化傷害在目標 #: data/json/items/ranged/crossbows.json msgid "aluminum field point bolt" msgid_plural "aluminum field point bolts" -msgstr[0] "" +msgstr[0] "铝制锥头弩矢" #. ~ Description for {'str': 'aluminum field point bolt'} #: data/json/items/ranged/crossbows.json @@ -91631,7 +91873,7 @@ msgstr "一根附有箭羽的鋁製十字弓弩箭,箭頭呈尖銳狀。適用 #: data/json/items/ranged/crossbows.json msgid "aluminum small game bolt" msgid_plural "aluminum small game bolts" -msgstr[0] "" +msgstr[0] "铝制狩猎小弩矢" #. ~ Description for {'str': 'aluminum small game bolt'} #: data/json/items/ranged/crossbows.json @@ -91644,7 +91886,7 @@ msgstr "附有箭羽的鋁製十字弓弩箭,箭頭呈鈍頭狀。適用於狩 #: data/json/items/ranged/crossbows.json msgid "carbon fiber hunting bolt" msgid_plural "carbon fiber hunting bolts" -msgstr[0] "" +msgstr[0] "碳素狩猎弩矢" #. ~ Description for {'str': 'carbon fiber hunting bolt'} #: data/json/items/ranged/crossbows.json @@ -91657,7 +91899,7 @@ msgstr "附有箭羽的碳纖維十字弓弩箭,箭頭呈擴張的寬頭狀。 #: data/json/items/ranged/crossbows.json msgid "explosive crossbow bolt" msgid_plural "explosive crossbow bolts" -msgstr[0] "" +msgstr[0] "爆裂弩矢" #. ~ Description for {'str': 'explosive crossbow bolt'} #: data/json/items/ranged/crossbows.json @@ -91767,7 +92009,7 @@ msgstr "孩童間受歡迎的玩具槍。命中率雖然不低, 可是BB彈幾 #: data/json/items/ranged/pneumatic.json msgid "pneumatic bolt driver" msgid_plural "pneumatic bolt drivers" -msgstr[0] "" +msgstr[0] "气动弩矢射枪" #: data/json/items/ranged/pneumatic.json msgid "" @@ -91779,7 +92021,7 @@ msgstr "废料手制而成的八发转管气动弩矢射枪。装填时要小心 #: data/json/items/ranged/pneumatic.json msgid "pneumatic assault rifle" msgid_plural "pneumatic assault rifles" -msgstr[0] "" +msgstr[0] "气动突击步枪" #: data/json/items/ranged/pneumatic.json msgid "" @@ -91792,7 +92034,7 @@ msgstr "废料手制而成的多冲程气动步枪。装填时要小心,泵入 msgctxt "weapon" msgid "sling" msgid_plural "slings" -msgstr[0] "" +msgstr[0] "投石索" #: data/json/items/ranged/slings.json msgid "" @@ -91802,7 +92044,7 @@ msgstr "一個皮製的投石帶, 很易用又準確。以小石子作為彈藥 #: data/json/items/ranged/slings.json msgid "staff sling" msgid_plural "staff slings" -msgstr[0] "" +msgstr[0] "投石杖" #: data/json/items/ranged/slings.json msgid "" @@ -91835,7 +92077,7 @@ msgstr "一個現代化的彈弓, 綁在手腕固定, 操作簡單, 準確, 而 #: data/json/items/ranged/spearguns.json msgid "wooden fishing spear" msgid_plural "wooden fishing spears" -msgstr[0] "" +msgstr[0] "木制枪矛" #. ~ Description for {'str': 'wooden fishing spear'} #: data/json/items/ranged/spearguns.json @@ -91848,7 +92090,7 @@ msgstr "一根被削尖的水下魚叉, 非常輕但射程並不遠, 在射出 #: data/json/items/ranged/spearguns.json msgid "carbon fiber fishing spear" msgid_plural "carbon fiber fishing spears" -msgstr[0] "" +msgstr[0] "碳素纤维枪矛" #. ~ Description for {'str': 'carbon fiber fishing spear'} #: data/json/items/ranged/spearguns.json @@ -91861,7 +92103,7 @@ msgstr "一根碳纖維製的水下魚叉, 非常輕但射程並不遠, 在射 #: data/json/items/ranged/spearguns.json msgid "metal fishing spear" msgid_plural "metal fishing spears" -msgstr[0] "" +msgstr[0] "金属枪矛" #. ~ Description for {'str': 'metal fishing spear'} #: data/json/items/ranged/spearguns.json @@ -91955,7 +92197,7 @@ msgstr "一個塑膠飛盤,戶外活動使用" #: data/json/items/ranged/throwing.json msgid "net" msgid_plural "nets" -msgstr[0] "" +msgstr[0] "网" #. ~ Description for {'str': 'net'} #: data/json/items/ranged/throwing.json @@ -92001,7 +92243,7 @@ msgstr "一支薄且扁平的投擲用小刀, 那並不鋒利的刀刃與奇特 #: data/json/items/ranged/throwing.json msgid "throwing stick" msgid_plural "throwing sticks" -msgstr[0] "" +msgstr[0] "掷棍" #. ~ Description for {'str': 'throwing stick'} #: data/json/items/ranged/throwing.json @@ -92039,7 +92281,7 @@ msgstr "這是一個大形莢,大小像 10 加侖桶,裡面充滿了黏糊 #: data/json/items/resources/chemicals.json msgid "potassium alum" msgid_plural "potassium alums" -msgstr[0] "" +msgstr[0] "钾矾" #. ~ Description for {'str': 'potassium alum'} #: data/json/items/resources/chemicals.json @@ -92054,7 +92296,7 @@ msgstr "" #: data/json/items/resources/chemicals.json msgid "cloth dye powder" msgid_plural "cloth dye powders" -msgstr[0] "" +msgstr[0] "染布染料粉" #. ~ Description for {'str': 'cloth dye powder'} #: data/json/items/resources/chemicals.json @@ -92066,7 +92308,7 @@ msgstr "這是一種粉狀的彩色布料染料,如果與水和某些媒染劑 #: data/json/items/resources/fasteners.json msgid "steel buckle" msgid_plural "steel buckles" -msgstr[0] "" +msgstr[0] "钢制带扣" #. ~ Description for {'str': 'steel buckle'} #: data/json/items/resources/fasteners.json @@ -92076,7 +92318,7 @@ msgstr "鋼製帶釦,像似皮帶上的那種。" #: data/json/items/resources/fasteners.json msgid "plastic button" msgid_plural "plastic buttons" -msgstr[0] "" +msgstr[0] "塑料纽扣" #. ~ Description for {'str': 'plastic button'} #: data/json/items/resources/fasteners.json @@ -92086,7 +92328,7 @@ msgstr "塑膠鈕扣,通常能在衣服上找到。" #: data/json/items/resources/fasteners.json msgid "steel button" msgid_plural "steel buttons" -msgstr[0] "" +msgstr[0] "钢制纽扣" #. ~ Description for {'str': 'steel button'} #: data/json/items/resources/fasteners.json @@ -92096,7 +92338,7 @@ msgstr "鋼質鈕扣,通常能在衣服上找到。" #: data/json/items/resources/fasteners.json msgid "wooden button" msgid_plural "wooden buttons" -msgstr[0] "" +msgstr[0] "木制纽扣" #. ~ Description for {'str': 'wooden button'} #: data/json/items/resources/fasteners.json @@ -92106,7 +92348,7 @@ msgstr "粗糙的木質鈕扣,通常能在很舊的衣服上找到。" #: data/json/items/resources/fasteners.json msgid "steel snap fastener" msgid_plural "steel snap fasteners" -msgstr[0] "" +msgstr[0] "钢制按扣" #. ~ Description for {'str': 'steel snap fastener'} #: data/json/items/resources/fasteners.json @@ -92116,7 +92358,7 @@ msgstr "鋼質子母扣,通常能在衣服上找到。" #: data/json/items/resources/fasteners.json msgid "touch fastener" msgid_plural "touch fasteners" -msgstr[0] "" +msgstr[0] "魔术贴" #. ~ Description for {'str': 'touch fastener'} #: data/json/items/resources/fasteners.json @@ -92128,7 +92370,7 @@ msgstr "這是一對布條,其中一個布條佈滿微小的鉤線,而另一 #: data/json/items/resources/fasteners.json msgid "long plastic zipper" msgid_plural "long plastic zippers" -msgstr[0] "" +msgstr[0] "长塑料拉链" #. ~ Description for {'str': 'long plastic zipper'} #: data/json/items/resources/fasteners.json @@ -92138,7 +92380,7 @@ msgstr "塑膠製的長拉鍊,通常能在衣服上找到。" #: data/json/items/resources/fasteners.json msgid "short plastic zipper" msgid_plural "short plastic zippers" -msgstr[0] "" +msgstr[0] "短塑料拉链" #. ~ Description for {'str': 'short plastic zipper'} #: data/json/items/resources/fasteners.json @@ -92203,7 +92445,7 @@ msgstr "利用鋼線強化的的玻璃窗框。" #: data/json/items/resources/glass.json msgid "sheet of tempered glass" msgid_plural "sheets of tempered glass" -msgstr[0] "" +msgstr[0] "钢化玻璃片" #. ~ Description for {'str': 'sheet of tempered glass', 'str_pl': 'sheets of #. tempered glass'} @@ -92330,7 +92572,7 @@ msgstr "一根鋼管, 能作為良好的近戰武器。能用於某些物品製 #: data/json/items/resources/metal.json msgid "scrap metal" msgid_plural "scrap metals" -msgstr[0] "" +msgstr[0] "金属废料" #. ~ Description for {'str': 'scrap metal'} #: data/json/items/resources/metal.json @@ -92460,7 +92702,7 @@ msgstr "" #: data/json/items/resources/metal.json msgid "small metal sheet" msgid_plural "small metal sheets" -msgstr[0] "" +msgstr[0] "小型薄钢板" #. ~ Description for {'str': 'small metal sheet'} #: data/json/items/resources/metal.json @@ -92470,7 +92712,7 @@ msgstr "一片小型金屬板。" #: data/json/items/resources/metal.json msgid "chunk of steel" msgid_plural "chunks of steel" -msgstr[0] "" +msgstr[0] "钢块" #. ~ Description for {'str': 'chunk of steel', 'str_pl': 'chunks of steel'} #: data/json/items/resources/metal.json @@ -92482,7 +92724,7 @@ msgstr "一個畸形的鋼塊, 能作為不錯的武器, 也能用於一些物 #: data/json/items/resources/metal.json msgid "lump of steel" msgid_plural "lumps of steel" -msgstr[0] "" +msgstr[0] "钢锭" #. ~ Description for {'str': 'lump of steel', 'str_pl': 'lumps of steel'} #: data/json/items/resources/metal.json @@ -92492,7 +92734,7 @@ msgstr "一個沉重的鋼塊。能用於一些物品製作配方。" #: data/json/items/resources/metal.json msgid "door hinge" msgid_plural "door hinges" -msgstr[0] "" +msgstr[0] "门铰链" #. ~ Description for {'str': 'door hinge'} #: data/json/items/resources/metal.json @@ -92526,7 +92768,7 @@ msgstr "锡可以用来制作焊料,也可以镀在容器上防止腐蚀。" #: data/json/items/resources/metal.json msgid "solder" msgid_plural "solder" -msgstr[0] "" +msgstr[0] "焊料" #. ~ Description for {'str_sp': 'solder'} #: data/json/items/resources/metal.json @@ -92660,7 +92902,7 @@ msgstr "這是一個塑膠塊, 能用於製造、修理或強化塑膠製成的 #: data/json/items/resources/plastic.json msgid "synthetic fabric" msgid_plural "synthetic fabric" -msgstr[0] "" +msgstr[0] "化纤布片" #. ~ Description for {'str_sp': 'synthetic fabric'} #: data/json/items/resources/plastic.json @@ -92685,7 +92927,7 @@ msgstr "這是一大張厚重的軟塑膠,可用於商業包裝或家用防水 #: data/json/items/resources/plastic.json msgid "rigid plastic sheet" msgid_plural "rigid plastic sheets" -msgstr[0] "" +msgstr[0] "硬塑料板" #. ~ Description for rigid plastic sheet #: data/json/items/resources/plastic.json @@ -92697,7 +92939,7 @@ msgstr "一整片坚硬的半透明塑料,可用于各种用途;从搭建建 #: data/json/items/resources/plastic.json msgid "plastic scrap" msgid_plural "plastic scraps" -msgstr[0] "" +msgstr[0] "塑料废料" #. ~ Description for {'str': 'plastic scrap'} #: data/json/items/resources/plastic.json @@ -92824,7 +93066,7 @@ msgstr "形狀奇特的諾梅克斯纖維細屑,是裁縫加工後剩餘的廢 #: data/json/items/resources/tailoring.json msgid "cotton sheet" msgid_plural "cotton sheets" -msgstr[0] "" +msgstr[0] "棉布面料" #. ~ Description for {'str': 'cotton sheet'} #: data/json/items/resources/tailoring.json @@ -92834,7 +93076,7 @@ msgstr "一大片棉織品布料,適合用於製作衣服。" #: data/json/items/resources/tailoring.json msgid "patchwork cotton clothing parts" msgid_plural "patchwork cotton clothing parts" -msgstr[0] "" +msgstr[0] "棉布拼布" #. ~ Description for {'str_sp': 'patchwork cotton clothing parts'} #: data/json/items/resources/tailoring.json @@ -92847,7 +93089,7 @@ msgstr "各类衣物部件,由棉布片采用拼布工艺缝制而成。可以 #: data/json/items/resources/tailoring.json msgid "faux fur sheet" msgid_plural "faux fur sheets" -msgstr[0] "" +msgstr[0] "人造毛皮面料" #. ~ Description for {'str': 'faux fur sheet'} #: data/json/items/resources/tailoring.json @@ -92857,7 +93099,7 @@ msgstr "一大片假的合成彩色毛皮,適合用於製作衣服。" #: data/json/items/resources/tailoring.json msgid "patchwork faux fur clothing parts" msgid_plural "patchwork faux fur clothing parts" -msgstr[0] "" +msgstr[0] "人造毛皮拼布" #. ~ Description for {'str_sp': 'patchwork faux fur clothing parts'} #: data/json/items/resources/tailoring.json @@ -92870,7 +93112,7 @@ msgstr "各类衣物部件,由人造毛皮片采用拼布工艺缝制而成。 #: data/json/items/resources/tailoring.json msgid "felt sheet" msgid_plural "felt sheets" -msgstr[0] "" +msgstr[0] "毛毡面料" #. ~ Description for {'str': 'felt sheet'} #: data/json/items/resources/tailoring.json @@ -92880,7 +93122,7 @@ msgstr "一大片毛氈布料,適合用於製作衣服。" #: data/json/items/resources/tailoring.json msgid "patchwork felt clothing parts" msgid_plural "patchwork felt clothing parts" -msgstr[0] "" +msgstr[0] "毛毡拼布" #. ~ Description for {'str_sp': 'patchwork felt clothing parts'} #: data/json/items/resources/tailoring.json @@ -92893,7 +93135,7 @@ msgstr "各类衣物部件,由毛毡片采用拼布工艺缝制而成。可以 #: data/json/items/resources/tailoring.json msgid "Kevlar sheet" msgid_plural "Kevlar sheets" -msgstr[0] "" +msgstr[0] "凯夫拉面料" #. ~ Description for {'str': 'Kevlar sheet'} #: data/json/items/resources/tailoring.json @@ -92905,7 +93147,7 @@ msgstr "一大片凱夫勒合成纖維,適合製作防彈護甲。與剛性板 #: data/json/items/resources/tailoring.json msgid "neoprene sheet" msgid_plural "neoprene sheets" -msgstr[0] "" +msgstr[0] "氯丁橡胶面料" #. ~ Description for {'str': 'neoprene sheet'} #: data/json/items/resources/tailoring.json @@ -92917,7 +93159,7 @@ msgstr "一卷人工合成的氯丁橡胶。可以用来制造水下作业的衣 #: data/json/items/resources/tailoring.json msgid "patchwork neoprene clothing parts" msgid_plural "patchwork neoprene clothing parts" -msgstr[0] "" +msgstr[0] "氯丁橡胶拼布" #. ~ Description for {'str_sp': 'patchwork neoprene clothing parts'} #: data/json/items/resources/tailoring.json @@ -92931,7 +93173,7 @@ msgstr "各类衣物部件,由氯丁橡胶片采用拼布工艺缝制而成。 #: data/json/items/resources/tailoring.json msgid "Nomex sheet" msgid_plural "Nomex sheets" -msgstr[0] "" +msgstr[0] "芳纶面料" #. ~ Description for {'str': 'Nomex sheet'} #: data/json/items/resources/tailoring.json @@ -92943,7 +93185,7 @@ msgstr "一大片諾梅克斯布料,適合用於製作耐熱衣服。" #: data/json/items/resources/tailoring.json msgid "patchwork Nomex clothing parts" msgid_plural "patchwork Nomex clothing parts" -msgstr[0] "" +msgstr[0] "芳纶拼布" #. ~ Description for {'str_sp': 'patchwork Nomex clothing parts'} #: data/json/items/resources/tailoring.json @@ -92956,7 +93198,7 @@ msgstr "各类衣物部件,由芳纶片采用拼布工艺缝制而成。可以 #: data/json/items/resources/tailoring.json msgid "synthetic fabric sheet" msgid_plural "synthetic fabric sheets" -msgstr[0] "" +msgstr[0] "化纤面料" #. ~ Description for {'str': 'synthetic fabric sheet'} #: data/json/items/resources/tailoring.json @@ -92966,7 +93208,7 @@ msgstr "一大片合成纖維布料,適合用於製作衣服。" #: data/json/items/resources/tailoring.json msgid "patchwork synthetic fabric clothing parts" msgid_plural "patchwork synthetic fabric clothing parts" -msgstr[0] "" +msgstr[0] "化纤拼布" #. ~ Description for {'str_sp': 'patchwork synthetic fabric clothing parts'} #: data/json/items/resources/tailoring.json @@ -92979,7 +93221,7 @@ msgstr "各类衣物部件,由化纤片采用拼布工艺缝制而成。可以 #: data/json/items/resources/tailoring.json msgid "Kevlar thread" msgid_plural "Kevlar threads" -msgstr[0] "" +msgstr[0] "凯夫拉纤维" #. ~ Description for {'str': 'Kevlar thread'} #: data/json/items/resources/tailoring.json @@ -92994,7 +93236,7 @@ msgstr "" #: data/json/items/resources/tailoring.json msgid "Nomex thread" msgid_plural "Nomex threads" -msgstr[0] "" +msgstr[0] "芳纶纤维" #. ~ Description for {'str': 'Nomex thread'} #: data/json/items/resources/tailoring.json @@ -93019,7 +93261,7 @@ msgstr "一大塊原木,從樹上砍下來的。使用木斧或木鋸將其切 #: data/json/items/resources/wood.json msgid "splintered wood" msgid_plural "splintered wood" -msgstr[0] "" +msgstr[0] "碎木" #. ~ Description for {'str_sp': 'splintered wood'} #: data/json/items/resources/wood.json @@ -93157,7 +93399,7 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "butchering kit" msgid_plural "butchering kits" -msgstr[0] "" +msgstr[0] "屠宰工具箱" #. ~ Description for {'str': 'butchering kit'} #: data/json/items/tool/cooking.json @@ -93169,7 +93411,7 @@ msgstr "这是一个包含各式各样专业刀具的工具箱,能满足你一 #: data/json/items/tool/cooking.json msgid "pseudo butter churn" msgid_plural "pseudo butter churns" -msgstr[0] "" +msgstr[0] "虚拟黄油搅拌机" #. ~ Description for {'str': 'pseudo butter churn'} #. ~ Description for {'str': 'deployed atomic butter churn'} @@ -93349,7 +93591,7 @@ msgstr "被稱為 Esbit 爐, 這是一種輕量的折疊式煮食爐, 使用小 #: data/json/items/tool/cooking.json msgid "sealed yeast culture" msgid_plural "sealed yeast culture" -msgstr[0] "" +msgstr[0] "密封酵母" #. ~ Use action msg for {'str_sp': 'sealed yeast culture'}. #: data/json/items/tool/cooking.json @@ -93385,7 +93627,7 @@ msgstr "装满了洗干净的酵母增殖原料的密封罐。当发酵完毕你 #: data/json/items/tool/cooking.json msgid "sealed wild yeast culture" msgid_plural "sealed wild yeast culture" -msgstr[0] "" +msgstr[0] "密封野生酵母" #. ~ Description for {'str_sp': 'sealed wild yeast culture'} #: data/json/items/tool/cooking.json @@ -93559,7 +93801,7 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "mortar and pestle" msgid_plural "mortars and pestles" -msgstr[0] "" +msgstr[0] "研钵和杵" #. ~ Description for {'str': 'mortar and pestle', 'str_pl': 'mortars and #. pestles'} @@ -93589,7 +93831,7 @@ msgstr "" #: data/json/items/tool/cooking.json msgid "multi cooker - cooking" msgid_plural "multi cooker - cookings" -msgstr[0] "" +msgstr[0] "多功能厨师机(烹饪中)" #. ~ Description for {'str': 'multi cooker - cooking'} #: data/json/items/tool/cooking.json @@ -93823,7 +94065,7 @@ msgstr[0] "充氣船" #. ~ Use action unfold_msg for {'str': 'inflatable boat'}. #: data/json/items/tool/deployable.json msgid "You painstakingly unfold, inflate, and launch the %s." -msgstr "" +msgstr "你费劲地展开了%s,并给它充气,准备使用它。" #. ~ Description for {'str': 'inflatable boat'} #: data/json/items/tool/deployable.json @@ -93865,7 +94107,7 @@ msgstr "一种由纤维材料编织而成的大垫子,可代替野餐毯,但 #: data/json/items/tool/deployable.json msgid "folded butter churn" msgid_plural "folded butter churns" -msgstr[0] "" +msgstr[0] "黄油搅拌机(折叠)" #. ~ Description for {'str': 'folded butter churn'} #: data/json/items/tool/deployable.json @@ -93918,7 +94160,7 @@ msgstr "一台傻瓜型數位相機, 有液晶螢幕, 備用的觀景窗, 以及 #: data/json/items/tool/electronics.json msgid "professional camera" msgid_plural "professional cameras" -msgstr[0] "" +msgstr[0] "专业相机" #. ~ Description for {'str': 'professional camera'} #: data/json/items/tool/electronics.json @@ -93962,7 +94204,7 @@ msgstr "" #: data/json/items/tool/electronics.json msgid "cellphone - Screenlight" msgid_plural "cellphones - Screenlight" -msgstr[0] "" +msgstr[0] "手机(屏幕光)" #. ~ Use action msg for {'str': 'cellphone - Screenlight', 'str_pl': #. 'cellphones - Screenlight'}. @@ -94093,7 +94335,7 @@ msgstr "一台使用UPS的笔记本电脑。" #: data/json/items/tool/electronics.json msgid "laptop computer - lit screen" msgid_plural "laptop computers - lit screen" -msgstr[0] "" +msgstr[0] "笔记本电脑(点亮)" #: data/json/items/tool/electronics.json msgid "mp3 player (off)" @@ -94262,7 +94504,7 @@ msgstr "這個吃電池的裝置是用來幫你按摩舒緩僵硬的身體, 使 #: data/json/items/tool/electronics.json msgid "bionic scanner" msgid_plural "bionic scanners" -msgstr[0] "" +msgstr[0] "生化插件扫描仪" #. ~ Use action msg for {'str': 'bionic scanner'}. #: data/json/items/tool/electronics.json @@ -94284,7 +94526,7 @@ msgstr "一台专门用于探测生化插件的小型金属扫描仪。激活以 #: data/json/items/tool/electronics.json msgid "bionic scanner (on)" msgid_plural "bionic scanner (on)s" -msgstr[0] "" +msgstr[0] "生化插件扫描仪(开)" #. ~ Description for {'str': 'bionic scanner (on)'} #: data/json/items/tool/electronics.json @@ -94370,7 +94612,7 @@ msgstr[0] "生物開鎖工具" #: data/json/items/tool/explosives.json msgid "debug shrapnel" msgid_plural "debug shrapnels" -msgstr[0] "" +msgstr[0] "调试用弹片" #. ~ Description for {'str': 'debug shrapnel'} #: data/json/items/tool/explosives.json @@ -94394,7 +94636,7 @@ msgstr "一個裝滿強酸的易碎容器。丟出去就會成為酸液灘。" #: data/json/items/tool/explosives.json msgid "can bomb" msgid_plural "can bombs" -msgstr[0] "" +msgstr[0] "锡罐炸弹" #. ~ Use action msg for {'str': 'can bomb'}. #: data/json/items/tool/explosives.json @@ -94413,7 +94655,7 @@ msgstr "这是一个装满了某种炸药的锡罐,带有一个引信。爆炸 #: data/json/items/tool/explosives.json msgid "active can bomb" msgid_plural "active can bombs" -msgstr[0] "" +msgstr[0] "锡罐炸弹(无保险)" #. ~ Description for {'str': 'active can bomb'} #: data/json/items/tool/explosives.json @@ -94491,7 +94733,7 @@ msgstr "這個炸藥的引線已經點燃並嘶嘶作響。將會隨時被引爆 #: data/json/items/tool/explosives.json msgid "dynamite bomb" msgid_plural "dynamite bombs" -msgstr[0] "" +msgstr[0] "炸药炸弹" #. ~ Description for {'str': 'dynamite bomb'} #: data/json/items/tool/explosives.json @@ -94507,7 +94749,7 @@ msgstr "" #: data/json/items/tool/explosives.json msgid "dynamite bomb (lit)" msgid_plural "dynamite bombs (lit)" -msgstr[0] "" +msgstr[0] "炸药炸弹(点燃)" #. ~ Description for {'str': 'dynamite bomb (lit)', 'str_pl': 'dynamite bombs #. (lit)'} @@ -94520,7 +94762,7 @@ msgstr "引信嘶嘶地燃烧着,炸药炸弹随时都会爆炸!" #: data/json/items/tool/explosives.json msgid "EMP bomb" msgid_plural "EMP bombs" -msgstr[0] "" +msgstr[0] "EMP炸弹" #. ~ Use action menu_text for {'str': 'EMP bomb'}. #: data/json/items/tool/explosives.json @@ -94545,7 +94787,7 @@ msgstr "" #: data/json/items/tool/explosives.json msgid "active EMP bomb" msgid_plural "active EMP bombs" -msgstr[0] "" +msgstr[0] "EMP炸弹(激活)" #. ~ Use action no_deactivate_msg for {'str': 'active EMP bomb'}. #: data/json/items/tool/explosives.json @@ -94565,7 +94807,7 @@ msgstr "" #: data/json/items/tool/explosives.json msgid "improvised demolition charge" msgid_plural "improvised demolition charges" -msgstr[0] "" +msgstr[0] "自制炸药包" #. ~ Description for {'str': 'improvised demolition charge'} #: data/json/items/tool/explosives.json @@ -94578,7 +94820,7 @@ msgstr "这是一个自制的炸药包。激活此物品可以点燃它,当然 #: data/json/items/tool/explosives.json msgid "improvised demolition charge (lit)" msgid_plural "improvised demolition charges (lit)" -msgstr[0] "" +msgstr[0] "自制炸药包(点燃)" #. ~ Description for {'str': 'improvised demolition charge (lit)', 'str_pl': #. 'improvised demolition charges (lit)'} @@ -95015,7 +95257,7 @@ msgstr "這是一把 M72 火箭筒, 目前已經裝彈了。隨時使用它就 #: data/json/items/tool/explosives.json msgid "improvised grenade" msgid_plural "improvised grenades" -msgstr[0] "" +msgstr[0] "自制手雷" #. ~ Use action msg for {'str': 'improvised grenade'}. #: data/json/items/tool/explosives.json @@ -95035,7 +95277,7 @@ msgstr "用各种零件拼凑成的自制手雷。使用此物品来点燃导火 #: data/json/items/tool/explosives.json msgid "active improvised grenade" msgid_plural "active improvised grenades" -msgstr[0] "" +msgstr[0] "自制手雷(点燃)" #. ~ Use action no_deactivate_msg for {'str': 'active improvised grenade'}. #: data/json/items/tool/explosives.json @@ -95102,7 +95344,7 @@ msgstr "一瓶塞着一块点燃的破布的易燃液体。投出去就能令火 #: data/json/items/tool/explosives.json msgid "improvised pipe bomb" msgid_plural "improvised pipe bombs" -msgstr[0] "" +msgstr[0] "自制雷管" #. ~ Description for {'str': 'improvised pipe bomb'} #: data/json/items/tool/explosives.json @@ -95115,7 +95357,7 @@ msgstr "一根塞满了稳定炸药的钢管,带有引信。使用此物品来 #: data/json/items/tool/explosives.json msgid "active improvised pipe bomb" msgid_plural "active improvised pipe bombs" -msgstr[0] "" +msgstr[0] "自制雷管(点燃)" #: data/json/items/tool/explosives.json msgid "scrambler grenade" @@ -95179,7 +95421,7 @@ msgstr "這個煙霧彈的插梢已被拔出, 正在釋出濃厚的煙霧。" #: data/json/items/tool/explosives.json msgid "small improvised frag device" msgid_plural "small improvised frag devices" -msgstr[0] "" +msgstr[0] "自制爆炸装置" #. ~ Use action msg for {'str': 'small improvised frag device'}. #: data/json/items/tool/explosives.json @@ -95208,7 +95450,7 @@ msgstr "这是一个自制的爆炸装置,由一个装满了稳定炸药和废 #: data/json/items/tool/explosives.json msgid "improvised barrel bomb" msgid_plural "improvised barrel bombs" -msgstr[0] "" +msgstr[0] "自制油罐炸弹" #. ~ Use action msg for {'str': 'improvised barrel bomb'}. #: data/json/items/tool/explosives.json @@ -95227,7 +95469,7 @@ msgstr "一个装满了许多稳定炸药的金属罐。起爆药放置在核心 #: data/json/items/tool/explosives.json msgid "active improvised barrel bomb" msgid_plural "active improvised barrel bombs" -msgstr[0] "" +msgstr[0] "自制油罐炸弹(点燃)" #. ~ Description for {'str': 'active improvised barrel bomb'} #: data/json/items/tool/explosives.json @@ -95240,7 +95482,7 @@ msgstr "一个装满了许多稳定炸药的金属罐。导火索已经点燃了 #: data/json/items/tool/explosives.json msgid "rocket candy" msgid_plural "rocket candies" -msgstr[0] "" +msgstr[0] "火箭软糖" #. ~ Use action menu_text for {'str': 'rocket candy', 'str_pl': 'rocket #. candies'}. @@ -95266,7 +95508,7 @@ msgstr "" #: data/json/items/tool/explosives.json msgid "burning rocket candy" msgid_plural "burning rocket candies" -msgstr[0] "" +msgstr[0] "火箭软糖(燃烧)" #. ~ Use action no_deactivate_msg for {'str': 'burning rocket candy', #. 'str_pl': 'burning rocket candies'}. @@ -95474,7 +95716,7 @@ msgstr "一个用来装引火物的小盒子,盒子上有个小洞以保持空 #: data/json/items/tool/firefighting.json msgid "crash axe" msgid_plural "crash axes" -msgstr[0] "" +msgstr[0] "应急斧" #. ~ Description for {'str': 'crash axe'} #: data/json/items/tool/firefighting.json @@ -95551,7 +95793,7 @@ msgstr "這是一個有著手榴彈外形的滅火器, 效果雖不如常規滅 #: data/json/items/tool/firefighting.json msgid "pike pole" msgid_plural "pike poles" -msgstr[0] "" +msgstr[0] "消防火钩" #. ~ Description for {'str': 'pike pole'} #: data/json/items/tool/firefighting.json @@ -95565,7 +95807,7 @@ msgstr "" #: data/json/items/tool/firefighting.json msgid "New York hook" msgid_plural "New York hooks" -msgstr[0] "" +msgstr[0] "纽约钩" #. ~ Description for {'str': 'New York hook'} #: data/json/items/tool/firefighting.json @@ -95636,7 +95878,7 @@ msgstr "一把專業的釣魚竿, 配有一套適合的鉛錘。有了這個你 #: data/json/items/tool/handloading.json msgid "hand press" msgid_plural "hand presses" -msgstr[0] "" +msgstr[0] "手动压弹机" #. ~ Description for {'str': 'hand press', 'str_pl': 'hand presses'} #: data/json/items/tool/handloading.json @@ -95648,7 +95890,7 @@ msgstr "一個小型的手壓模具, 讓你可以手工組裝槍枝的子彈。 #: data/json/items/tool/handloading.json msgid "makeshift shotshell press" msgid_plural "makeshift shotshell presses" -msgstr[0] "" +msgstr[0] "简易霰弹压弹机" #. ~ Description for {'str': 'makeshift shotshell press', 'str_pl': 'makeshift #. shotshell presses'} @@ -95958,7 +96200,7 @@ msgstr "一根粗蠟燭, 雖然提供不了多少光亮, 但可以持續燃燒 #: data/json/items/tool/lighting.json msgid "candle (lit)" msgid_plural "candles (lit)" -msgstr[0] "" +msgstr[0] "蜡烛(点燃)" #. ~ Use action msg for {'str': 'candle (lit)', 'str_pl': 'candles (lit)'}. #: data/json/items/tool/lighting.json @@ -96204,7 +96446,7 @@ msgstr "你把耐用手電筒關掉。" #: data/json/items/tool/lighting.json msgid "lightstrip_base" msgid_plural "lightstrip_bases" -msgstr[0] "" +msgstr[0] "灯带(基础)" #: data/json/items/tool/lighting.json msgid "lightstrip" @@ -96253,7 +96495,7 @@ msgstr "一盞以燈油為燃料的燈。不能夠提供大量照明, 但是能 #: data/json/items/tool/lighting.json msgid "oil lamp" msgid_plural "oil lamps" -msgstr[0] "" +msgstr[0] "油灯" #. ~ Description for {'str': 'oil lamp'} #: data/json/items/tool/lighting.json @@ -96419,7 +96661,7 @@ msgstr "吸飽易燃物的布料纏繞在這大木棍上。點燃它可以發出 #: data/json/items/tool/masonry.json msgid "masonry saw (off)" msgid_plural "masonry saws (off)" -msgstr[0] "" +msgstr[0] "切砖机(关)" #. ~ Description for {'str': 'masonry saw (off)', 'str_pl': 'masonry saws #. (off)'} @@ -96433,7 +96675,7 @@ msgstr "一台用于切割混凝土或其他表面的建筑工具。它以汽油 #: data/json/items/tool/masonry.json msgid "masonry saw (on)" msgid_plural "masonry saws (on)" -msgstr[0] "" +msgstr[0] "切砖机(开)" #. ~ Description for {'str': 'masonry saw (on)', 'str_pl': 'masonry saws #. (on)'} @@ -96445,7 +96687,7 @@ msgstr "切砖机已经启动,发出可怕的噪声。激活它来关闭。" #: data/json/items/tool/masonry.json msgid "grinder blade" msgid_plural "grinder blades" -msgstr[0] "" +msgstr[0] "角磨刀片" #. ~ Description for {'str': 'grinder blade'} #: data/json/items/tool/masonry.json @@ -96840,7 +97082,7 @@ msgstr "一個發條鬧鐘。雖然鬧鐘的噪音讓你有起床氣, 但讓你 #: data/json/items/tool/misc.json msgid "can of butane" msgid_plural "cans of butane" -msgstr[0] "" +msgstr[0] "丁烷罐" #. ~ Description for {'str': 'can of butane', 'str_pl': 'cans of butane'} #: data/json/items/tool/misc.json @@ -96862,7 +97104,7 @@ msgstr "一个黄铜牛铃。你觉得你需要更多。(注:Need more cowbe #: data/json/items/tool/misc.json msgid "dab pen" msgid_plural "dab pens" -msgstr[0] "" +msgstr[0] "笔形电子烟" #. ~ Use action msg for {'str': 'dab pen'}. #: data/json/items/tool/misc.json @@ -96885,7 +97127,7 @@ msgstr "一根用电池供电的笔形电子烟,可以用来吸食大麻精油 #: data/json/items/tool/misc.json msgid "dab pen (on)" msgid_plural "dab pens (on)" -msgstr[0] "" +msgstr[0] "笔形电子烟(开)" #. ~ Use action msg for {'str': 'dab pen (on)', 'str_pl': 'dab pens (on)'}. #: data/json/items/tool/misc.json @@ -96902,7 +97144,7 @@ msgstr "一根用电池供电的笔形电子烟,已经打开了,就差一些 #: data/json/items/tool/misc.json msgid "Cube of Shame" msgid_plural "Cube of Shame" -msgstr[0] "" +msgstr[0] "耻辱立方" #. ~ Use action msg for {'str_sp': 'Cube of Shame'}. #: data/json/items/tool/misc.json @@ -96925,7 +97167,7 @@ msgstr "这是一个调试用的测试神器的物品。给它装上电池然后 #: data/json/items/tool/misc.json msgid "Cube of Shame (on)" msgid_plural "Cube of Shame (on)" -msgstr[0] "" +msgstr[0] "耻辱立方(开)" #. ~ Use action msg for {'str_sp': 'Cube of Shame (on)'}. #: data/json/items/tool/misc.json @@ -96942,7 +97184,7 @@ msgstr "这是一个调试用的测试神器的物品。丢下或者把它关掉 #: data/json/items/tool/misc.json msgid "Trapezohedron of Edginess" msgid_plural "Trapezohedron of Edginess" -msgstr[0] "" +msgstr[0] "急躁的偏方三八面体" #. ~ Description for {'str_sp': 'Trapezohedron of Edginess'} #: data/json/items/tool/misc.json @@ -97130,7 +97372,7 @@ msgstr "你關閉了供暖氣。" #: data/json/items/tool/misc.json msgid "lifestraw" msgid_plural "lifestraws" -msgstr[0] "" +msgstr[0] "生命饮管" #. ~ Description for {'str': 'lifestraw'} #: data/json/items/tool/misc.json @@ -97155,7 +97397,7 @@ msgstr "將大刀刃連接在一根長棍子上。它能造成可觀的傷害。 #: data/json/items/tool/misc.json msgid "mind splicer kit" msgid_plural "mind splicer kits" -msgstr[0] "" +msgstr[0] "意识连接工具套" #. ~ Description for {'str': 'mind splicer kit'} #: data/json/items/tool/misc.json @@ -97168,7 +97410,7 @@ msgstr "外科手术钳、链接电缆和一个小型智能手机一起被放在 #: data/json/items/tool/misc.json msgid "plastic gasket" msgid_plural "plastic gaskets" -msgstr[0] "" +msgstr[0] "塑料垫片" #. ~ Description for {'str': 'plastic gasket'} #: data/json/items/tool/misc.json @@ -97337,7 +97579,7 @@ msgstr "一個自製的可折疊望遠鏡。它的體積太大也不夠準確, #: data/json/items/tool/misc.json msgid "tear gas payload" msgid_plural "tear gas payloads" -msgstr[0] "" +msgstr[0] "催泪弹载体" #. ~ Use action msg for {'str': 'tear gas payload'}. #: data/json/items/tool/misc.json @@ -97354,7 +97596,7 @@ msgstr "这是被催泪弹无人机使用的虚拟物品,你不应该在调试 #: data/json/items/tool/misc.json msgid "active tear gas payload" msgid_plural "active tear gas payloads" -msgstr[0] "" +msgstr[0] "催泪弹载体(激活)" #. ~ Description for {'str': 'active tear gas payload'} #: data/json/items/tool/misc.json @@ -97389,7 +97631,7 @@ msgstr "臥了個大槽, 這貨著——火——啦!" #: data/json/items/tool/misc.json msgid "Whistle of Tindalos" msgid_plural "Whistles of Tindalos" -msgstr[0] "" +msgstr[0] "廷达罗斯之哨" #. ~ Description for {'str': 'Whistle of Tindalos', 'str_pl': 'Whistles of #. Tindalos'} @@ -97547,7 +97789,7 @@ msgstr "這是一個小哨子。當使用時, 能夠吹響出高頻音效, 能 #: data/json/items/tool/pets.json msgid "shears" msgid_plural "shears" -msgstr[0] "" +msgstr[0] "大剪刀" #. ~ Description for {'str_sp': 'shears'} #: data/json/items/tool/pets.json @@ -97557,7 +97799,7 @@ msgstr "这是一把用来剪羊毛的剪刀。" #: data/json/items/tool/pets.json msgid "electric shears" msgid_plural "electric shears" -msgstr[0] "" +msgstr[0] "电动剪" #. ~ Description for {'str_sp': 'electric shears'} #: data/json/items/tool/pets.json @@ -97567,7 +97809,7 @@ msgstr "这把电动剪可以更快的给动物剪毛。" #: data/json/items/tool/pets.json msgid "horse tack" msgid_plural "horse tacks" -msgstr[0] "" +msgstr[0] "鞍具" #. ~ Description for {'str': 'horse tack'} #: data/json/items/tool/pets.json @@ -97603,7 +97845,7 @@ msgstr "木製的容器,設計用來運送寵物。使用後選擇合適的動 #: data/json/items/tool/pets.json msgid "wooden dog whistle" msgid_plural "wooden dog whistles" -msgstr[0] "" +msgstr[0] "木制狗哨" #. ~ Description for {'str': 'wooden dog whistle'} #: data/json/items/tool/pets.json @@ -97616,7 +97858,7 @@ msgstr "一只硬木雕成的哨子,吹它的时候会产生一种高频的声 #: data/json/items/tool/radio_tools.json msgid "radio car base" msgid_plural "radio car bases" -msgstr[0] "" +msgstr[0] "遥控玩具车盒" #. ~ Description for {'str': 'radio car base'} #: data/json/items/tool/radio_tools.json @@ -97794,7 +98036,7 @@ msgstr "這是用來收集雨水的大型金屬漏斗。比塑膠漏斗難攜帶 #: data/json/items/tool/raincatchers.json msgid "tarp raincatcher" msgid_plural "tarp raincatchers" -msgstr[0] "" +msgstr[0] "防水帆布集雨器" #. ~ Use action done_message for {'str': 'tarp raincatcher'}. #: data/json/items/tool/raincatchers.json @@ -97872,7 +98114,7 @@ msgstr "使用直流電的一組電線與電極,通常是液態的電極。適 #: data/json/items/tool/science.json msgid "butane tank" msgid_plural "tanks of butane" -msgstr[0] "" +msgstr[0] "压缩丁烷罐" #. ~ Description for {'str': 'butane tank', 'str_pl': 'tanks of butane'} #: data/json/items/tool/science.json @@ -98177,7 +98419,7 @@ msgstr "" #: data/json/items/tool/science.json msgid "rotary evaporator" msgid_plural "rotary evaporators" -msgstr[0] "" +msgstr[0] "旋转蒸发仪" #. ~ Description for {'str': 'rotary evaporator'} #: data/json/items/tool/science.json @@ -98338,7 +98580,7 @@ msgstr "一個手工雕刻的木製煙管, 用來促進菸草工業發展的器 #: data/json/items/tool/stationary.json msgid "stapler" msgid_plural "staplers" -msgstr[0] "" +msgstr[0] "订书机" #. ~ Description for {'str': 'stapler'} #: data/json/items/tool/stationary.json @@ -98348,7 +98590,7 @@ msgstr "一种将纸张固定在一起的订书机。" #: data/json/items/tool/stationary.json msgid "pen" msgid_plural "pens" -msgstr[0] "" +msgstr[0] "圆珠笔" #. ~ Description for {'str': 'pen'} #: data/json/items/tool/stationary.json @@ -98371,7 +98613,7 @@ msgstr "一把耐用的工艺长剪刀。使用它可以衣物等棉制物品剪 #: data/json/items/tool/stationary.json msgid "paper" msgid_plural "papers" -msgstr[0] "" +msgstr[0] "纸" #. ~ Description for paper #: data/json/items/tool/stationary.json @@ -98469,7 +98711,7 @@ msgstr "" #: data/json/items/tool/tailoring.json msgid "tailoring pattern set" msgid_plural "tailoring pattern sets" -msgstr[0] "" +msgstr[0] "缝纫用模板" #. ~ Description for {'str': 'tailoring pattern set'} #: data/json/items/tool/tailoring.json @@ -98818,7 +99060,7 @@ msgstr "這是個堅韌的細索附加了一些工具的陷阱。絆索陷阱必 #: data/json/items/tool/traps.json msgid "glass shard trap" msgid_plural "glass shard traps" -msgstr[0] "" +msgstr[0] "玻璃碎片陷阱" #. ~ Use action done_message for {'str': 'glass shard trap'}. #: data/json/items/tool/traps.json @@ -99026,7 +99268,7 @@ msgstr "一堆简陋的泥砖,在你冒着生命危险出去的时候已经干 #: data/json/items/tool/workshop.json msgid "acetylene-gas machine" msgid_plural "acetylene-gas machines" -msgstr[0] "" +msgstr[0] "乙炔制造机" #. ~ Description for {'str': 'acetylene-gas machine'} #: data/json/items/tool/workshop.json @@ -99038,7 +99280,7 @@ msgstr "这个大型设备接受水和电石,产出常压的乙炔气。" #: data/json/items/tool/workshop.json msgid "angle grinder" msgid_plural "angle grinders" -msgstr[0] "" +msgstr[0] "角磨机" #. ~ Description for {'str': 'angle grinder'} #: data/json/items/tool/workshop.json @@ -99085,7 +99327,7 @@ msgstr "一個類似鑿子的工具, 用來刮除油漆。" #: data/json/items/tool/workshop.json msgid "clamp" msgid_plural "clamps" -msgstr[0] "" +msgstr[0] "夹具" #. ~ Description for {'str': 'clamp'} #: data/json/items/tool/workshop.json @@ -99251,7 +99493,7 @@ msgstr "這是個建築用的工具, 能夠鑽破硬石頭或是其他表面。 #: data/json/items/tool/workshop.json msgid "Auger" msgid_plural "Augers" -msgstr[0] "" +msgstr[0] "螺旋钻" #. ~ Description for {'str': 'Auger'} #: data/json/items/tool/workshop.json @@ -99517,7 +99759,7 @@ msgstr "這是一個巨大的金屬盒子, 裡面裝了齊全的工具, 可以 #: data/json/items/tool/workshop.json msgid "workshop toolbox" msgid_plural "workshop toolboxes" -msgstr[0] "" +msgstr[0] "工坊工具箱" #. ~ Description for {'str': 'workshop toolbox', 'str_pl': 'workshop #. toolboxes'} @@ -99621,7 +99863,7 @@ msgstr "一個可調整的扳手。它能作為不錯的近戰武器, 也能用 #: data/json/items/tool/workshop.json msgid "leather hose" msgid_plural "leather hoses" -msgstr[0] "" +msgstr[0] "皮软管" #. ~ Description for leather hose #: data/json/items/tool/workshop.json @@ -99634,7 +99876,7 @@ msgstr "这是一根用皮革制成的软管。防水又轻便,可以从车辆 #: data/json/items/tool/workshop.json msgid "makeshift hand drill" msgid_plural "makeshift hand drills" -msgstr[0] "" +msgstr[0] "简易手摇钻" #. ~ Description for {'str': 'makeshift hand drill'} #: data/json/items/tool/workshop.json @@ -99713,7 +99955,7 @@ msgstr "一種笨重但高效的發電機,設計用於連接在引擎上。" #: data/json/vehicleparts/vehicle_parts.json msgid "yoke and harness" msgid_plural "yokes and harnesses" -msgstr[0] "" +msgstr[0] "挽具" #. ~ Description for {'str': 'yoke and harness', 'str_pl': 'yokes and #. harnesses'} @@ -99943,7 +100185,7 @@ msgstr "正如你所看到的一样,这是跨接电缆:一小段多用铜线 #: data/json/vehicleparts/vehicle_parts.json msgid "heavy duty tow cable" msgid_plural "heavy duty tow cables" -msgstr[0] "" +msgstr[0] "重型牵引索" #. ~ Description for heavy duty tow cable #: data/json/items/vehicle/cables.json @@ -100151,7 +100393,7 @@ msgstr "一具載具追蹤裝置。把它裝在車上就能追蹤愛車位置了 #: data/json/items/vehicle/controls.json msgid "rein and tackle" msgid_plural "reins and tackles" -msgstr[0] "" +msgstr[0] "缰绳挽具" #. ~ Description for {'str': 'rein and tackle', 'str_pl': 'reins and tackles'} #: data/json/items/vehicle/controls.json @@ -100222,27 +100464,27 @@ msgstr "一組馬達、攝像機、以及許多電子模組組合在一起,能 #: data/json/items/vehicle/engine.json msgid "internal combustion engine" msgid_plural "internal combustion engines" -msgstr[0] "" +msgstr[0] "内燃机" #: data/json/items/vehicle/engine.json msgid "base diesel engine" msgid_plural "base diesel engines" -msgstr[0] "" +msgstr[0] "基础柴油引擎" #: data/json/items/vehicle/engine.json msgid "base gasoline engine" msgid_plural "base gasoline engines" -msgstr[0] "" +msgstr[0] "基础汽油引擎" #: data/json/items/vehicle/engine.json msgid "base steam engine" msgid_plural "base steam engines" -msgstr[0] "" +msgstr[0] "基础蒸汽引擎" #: data/json/items/vehicle/engine.json msgid "1-cylinder engine" msgid_plural "1-cylinder engines" -msgstr[0] "" +msgstr[0] "单缸引擎" #. ~ Description for {'str': '1-cylinder engine'} #: data/json/items/vehicle/engine.json @@ -100252,7 +100494,7 @@ msgstr "一個單缸四行程的內燃式引擎。" #: data/json/items/vehicle/engine.json msgid "large 1-cylinder engine" msgid_plural "large 1-cylinder engines" -msgstr[0] "" +msgstr[0] "大型单缸引擎" #. ~ Description for {'str': 'large 1-cylinder engine'} #: data/json/items/vehicle/engine.json @@ -100263,7 +100505,7 @@ msgstr "強力的高壓縮單缸四行程的內燃式引擎。" #: data/json/items/vehicle/engine.json msgid "Inline-4 engine" msgid_plural "Inline-4 engines" -msgstr[0] "" +msgstr[0] "四缸引擎" #. ~ Description for {'str': 'Inline-4 engine'} #: data/json/items/vehicle/engine.json @@ -100273,7 +100515,7 @@ msgstr "一個小又有力的四缸內燃式引擎。" #: data/json/items/vehicle/engine.json msgid "I6 diesel engine" msgid_plural "I6 diesel engines" -msgstr[0] "" +msgstr[0] "六缸直列柴油引擎" #. ~ Description for {'str': 'I6 diesel engine'} #: data/json/items/vehicle/engine.json @@ -100283,7 +100525,7 @@ msgstr "一個強力的直列式六缸柴油引擎。" #: data/json/items/vehicle/engine.json msgid "V-twin engine" msgid_plural "V-twin engines" -msgstr[0] "" +msgstr[0] "双缸引擎" #. ~ Description for {'str': 'V-twin engine'} #: data/json/items/vehicle/engine.json @@ -100293,7 +100535,7 @@ msgstr "一個雙缸四行程的內燃式引擎。" #: data/json/items/vehicle/engine.json msgid "V6 engine" msgid_plural "V6 engines" -msgstr[0] "" +msgstr[0] "六缸引擎" #. ~ Description for {'str': 'V6 engine'} #: data/json/items/vehicle/engine.json @@ -100303,7 +100545,7 @@ msgstr "一個強力的六缸內燃式引擎。" #: data/json/items/vehicle/engine.json msgid "V6 diesel engine" msgid_plural "V6 diesel engines" -msgstr[0] "" +msgstr[0] "六缸柴油引擎" #. ~ Description for {'str': 'V6 diesel engine'} #: data/json/items/vehicle/engine.json @@ -100313,7 +100555,7 @@ msgstr "一個強力的六缸內燃式柴油引擎。" #: data/json/items/vehicle/engine.json msgid "V8 engine" msgid_plural "V8 engines" -msgstr[0] "" +msgstr[0] "八缸引擎" #. ~ Description for {'str': 'V8 engine'} #: data/json/items/vehicle/engine.json @@ -100323,7 +100565,7 @@ msgstr "一個又大又強力的八缸內燃式引擎。" #: data/json/items/vehicle/engine.json msgid "V8 diesel engine" msgid_plural "V8 diesel engines" -msgstr[0] "" +msgstr[0] "八缸柴油引擎" #. ~ Description for {'str': 'V8 diesel engine'} #: data/json/items/vehicle/engine.json @@ -100333,7 +100575,7 @@ msgstr "一個又大又強力的八缸內燃式柴油引擎。" #: data/json/items/vehicle/engine.json msgid "V12 engine" msgid_plural "V12 engines" -msgstr[0] "" +msgstr[0] "十二缸引擎" #. ~ Description for {'str': 'V12 engine'} #: data/json/items/vehicle/engine.json @@ -100345,7 +100587,7 @@ msgstr "一個巨大而無比強力的十二缸內燃式引擎, 通常用於高 #: data/json/items/vehicle/engine.json msgid "V12 diesel engine" msgid_plural "V12 diesel engines" -msgstr[0] "" +msgstr[0] "十二缸柴油引擎" #. ~ Description for {'str': 'V12 diesel engine'} #: data/json/items/vehicle/engine.json @@ -100357,7 +100599,7 @@ msgstr "一個巨大而無比強力的十二缸內燃式引擎, 通常用於重 #: data/json/items/vehicle/engine.json msgid "makeshift steam engine" msgid_plural "makeshift steam engines" -msgstr[0] "" +msgstr[0] "简易蒸汽引擎" #. ~ Description for {'str': 'makeshift steam engine'} #: data/json/items/vehicle/engine.json @@ -100370,7 +100612,7 @@ msgstr "一台小型且粗糙的蒸汽機。一體化的鍋爐藉由燃燒煤炭 #: data/json/items/vehicle/engine.json msgid "small steam engine" msgid_plural "small steam engines" -msgstr[0] "" +msgstr[0] "小型蒸汽引擎" #. ~ Description for {'str': 'small steam engine'} #: data/json/items/vehicle/engine.json @@ -100383,7 +100625,7 @@ msgstr "一台小型的蒸汽機。一體化的鍋爐藉由燃燒煤炭, 將水 #: data/json/items/vehicle/engine.json msgid "medium steam engine" msgid_plural "medium steam engines" -msgstr[0] "" +msgstr[0] "中型蒸汽引擎" #. ~ Description for {'str': 'medium steam engine'} #: data/json/items/vehicle/engine.json @@ -100471,7 +100713,7 @@ msgstr "微型燃氣或柴油引擎的缸體。不與其他零件組合就沒有 #: data/json/items/vehicle/engine.json msgid "1350 hp gas turbine engine" msgid_plural "1350 hp gas turbine engines" -msgstr[0] "" +msgstr[0] "燃气涡轮发动机(1350马力)" #. ~ Description for {'str': '1350 hp gas turbine engine'} #: data/json/items/vehicle/engine.json @@ -100484,7 +100726,7 @@ msgstr "一种燃气涡轮发动机,通常用于军用车辆。以耗油率高 #: data/json/items/vehicle/engine.json msgid "1900 hp gas turbine engine" msgid_plural "1900 hp gas turbine engines" -msgstr[0] "" +msgstr[0] "燃气涡轮发动机(1900马力)" #. ~ Description for {'str': '1900 hp gas turbine engine'} #: data/json/items/vehicle/engine.json @@ -100497,7 +100739,7 @@ msgstr "一种大型燃气涡轮发动机,通常用于军用直升机。以耗 #: data/json/items/vehicle/engine.json msgid "6000 hp gas turbine engine" msgid_plural "6000 hp gas turbine engines" -msgstr[0] "" +msgstr[0] "燃气涡轮发动机(6000马力)" #. ~ Description for {'str': '6000 hp gas turbine engine'} #: data/json/items/vehicle/engine.json @@ -100737,7 +100979,7 @@ msgstr "一個由數根木頭和繩索綁製而成的小框架。製作物品時 #: data/json/items/vehicle/fuel_storage.json data/json/vehicleparts/tanks.json msgid "fuel bunker" msgid_plural "fuel bunkers" -msgstr[0] "" +msgstr[0] "燃料舱" #. ~ Description for {'str': 'fuel bunker'} #: data/json/items/vehicle/fuel_storage.json @@ -101038,7 +101280,7 @@ msgstr "一套配有揚聲器的立體聲系統, 內置一段簡單的旋律。 #: data/json/items/vehicle/plating.json msgid "sheet metal" msgid_plural "sheet metal" -msgstr[0] "" +msgstr[0] "薄钢板" #. ~ Description for {'str_sp': 'sheet metal'} #: data/json/items/vehicle/plating.json @@ -101048,7 +101290,7 @@ msgstr "一片薄金屬板。" #: data/json/items/vehicle/plating.json msgid "wired sheet metal" msgid_plural "wired sheet metal" -msgstr[0] "" +msgstr[0] "接线薄钢板" #. ~ Description for {'str_sp': 'wired sheet metal'} #: data/json/items/vehicle/plating.json @@ -101069,7 +101311,7 @@ msgstr "一塊由 2X4 木材組裝而成的木製裝甲板。" #: data/json/vehicleparts/vehicle_parts.json msgid "steel plating" msgid_plural "steel plating" -msgstr[0] "" +msgstr[0] "钢制装甲板" #. ~ Description for {'str_sp': 'steel plating'} #: data/json/items/vehicle/plating.json @@ -101080,7 +101322,7 @@ msgstr "一塊鋼製裝甲板。" #: data/json/vehicleparts/vehicle_parts.json msgid "superalloy plating" msgid_plural "superalloy plating" -msgstr[0] "" +msgstr[0] "超合金装甲板" #. ~ Description for {'str_sp': 'superalloy plating'} #: data/json/items/vehicle/plating.json @@ -101102,7 +101344,7 @@ msgstr "一塊堅韌的超合金,難以想像的硬度與韌性。" #: data/json/vehicleparts/vehicle_parts.json msgid "spiked plating" msgid_plural "spiked plating" -msgstr[0] "" +msgstr[0] "钉刺装甲板" #. ~ Description for {'str_sp': 'spiked plating'} #: data/json/items/vehicle/plating.json @@ -101270,7 +101512,7 @@ msgstr "以車輛電池為動力的焊接裝置, 它配有一個精巧的烙鐵 #: data/json/items/vehicle/rotor.json data/json/vehicleparts/rotor.json msgid "heavy-duty military rotors" msgid_plural "sets of heavy-duty military rotors" -msgstr[0] "" +msgstr[0] "重型军用直升机旋翼" #. ~ Description for {'str': 'heavy-duty military rotors', 'str_pl': 'sets of #. heavy-duty military rotors'} @@ -101281,7 +101523,7 @@ msgstr "一套军用攻击直升机所使用的四叶旋翼。" #: data/json/items/vehicle/rotor.json msgid "small civilian helicopter rotors" msgid_plural "sets of small civilian helicopter rotors" -msgstr[0] "" +msgstr[0] "小型民用直升机旋翼" #. ~ Description for {'str': 'small civilian helicopter rotors', 'str_pl': #. 'sets of small civilian helicopter rotors'} @@ -101555,7 +101797,7 @@ msgstr "這種高壓滅菌器已經裝配好能使用載具的電力來運轉。 #: data/json/items/vehicle/utilities.json msgid "mountable autodoc" msgid_plural "mountable autodocs" -msgstr[0] "" +msgstr[0] "车载全自动医疗仪" #. ~ Description for {'str': 'mountable autodoc'} #: data/json/items/vehicle/utilities.json @@ -101565,7 +101807,7 @@ msgstr "这个全自动医疗仪被改装过,可以使用载具上的电力来 #: data/json/items/vehicle/utilities.json msgid "mountable autodoc couch" msgid_plural "mountable autodoc couchs" -msgstr[0] "" +msgstr[0] "车载全自动医疗仪手术台" #. ~ Description for {'str': 'mountable autodoc couch'} #: data/json/items/vehicle/utilities.json @@ -101600,7 +101842,7 @@ msgstr "一台非常小的洗碗機,設計成能在車輛上使用。" #: data/json/items/vehicle/utilities.json msgid "refrigerated tank" msgid_plural "refrigerated tanks" -msgstr[0] "" +msgstr[0] "冷藏罐" #. ~ Description for {'str': 'refrigerated tank'} #: data/json/items/vehicle/utilities.json @@ -101633,7 +101875,7 @@ msgstr "一件帶孔的金屬,適用於自行車或摩托車輪胎。" #: data/json/items/vehicle/wheel.json msgid "medium wheel hub assembly" msgid_plural "medium wheel hub assemblies" -msgstr[0] "" +msgstr[0] "中型轮毂" #. ~ Description for {'str': 'medium wheel hub assembly', 'str_pl': 'medium #. wheel hub assemblies'} @@ -101645,7 +101887,7 @@ msgstr "金屬組件,可以用於將車輪固定在汽車上。適合汽車輪 #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "heavy wheel hub assembly" msgid_plural "heavy wheel hub assemblies" -msgstr[0] "" +msgstr[0] "重型轮毂" #. ~ Description for {'str': 'heavy wheel hub assembly', 'str_pl': 'heavy #. wheel hub assemblies'} @@ -101658,7 +101900,7 @@ msgstr "重型金屬組件,可以用於將車輪固定在汽車上。適合大 #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "wheel" msgid_plural "wheels" -msgstr[0] "" +msgstr[0] "车轮" #. ~ Description for {'str': 'wheel'} #: data/json/items/vehicle/wheel.json @@ -101668,7 +101910,7 @@ msgstr "一個汽車輪胎。" #: data/json/items/vehicle/wheel.json msgid "racing wheel" msgid_plural "racing wheels" -msgstr[0] "" +msgstr[0] "竞赛车轮" #. ~ Description for {'str': 'racing wheel'} #: data/json/items/vehicle/wheel.json @@ -101680,7 +101922,7 @@ msgstr "一個為賽車而設的寬闊、平滑的車輪,它光滑的表面能 #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "armored wheel" msgid_plural "armored wheels" -msgstr[0] "" +msgstr[0] "装甲车轮" #. ~ Description for {'str': 'armored wheel'} #: data/json/items/vehicle/wheel.json @@ -101690,7 +101932,7 @@ msgstr "一個軍用的寬輪胎。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "wheelbarrow wheel" msgid_plural "wheelbarrow wheels" -msgstr[0] "" +msgstr[0] "手推车轮" #. ~ Description for {'str': 'wheelbarrow wheel'} #: data/json/items/vehicle/wheel.json @@ -101700,7 +101942,7 @@ msgstr "一個小輪胎, 來自常見的花園獨輪手推車。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "bicycle wheel" msgid_plural "bicycle wheels" -msgstr[0] "" +msgstr[0] "自行车轮" #. ~ Description for {'str': 'bicycle wheel'} #: data/json/items/vehicle/wheel.json @@ -101710,7 +101952,7 @@ msgstr "一個自行車輪胎。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "off-road bicycle wheel" msgid_plural "off-road bicycle wheels" -msgstr[0] "" +msgstr[0] "越野自行车轮" #. ~ Description for {'str': 'off-road bicycle wheel'} #: data/json/items/vehicle/wheel.json @@ -101730,7 +101972,7 @@ msgstr "一組購物車的腳輪。" #: data/json/items/vehicle/wheel.json msgid "set of wheels" msgid_plural "sets of wheels" -msgstr[0] "" +msgstr[0] "一套轮子" #. ~ Description for {'str': 'set of wheels', 'str_pl': 'sets of wheels'} #: data/json/items/vehicle/wheel.json @@ -101740,7 +101982,7 @@ msgstr "一套由结实的轮胎橡胶制成的四个小轮子。" #: data/json/items/vehicle/wheel.json data/json/obsoletion/uncategorized.json msgid "metal wheel" msgid_plural "metal wheels" -msgstr[0] "" +msgstr[0] "金属车轮" #. ~ Description for {'str': 'metal wheel'} #: data/json/items/vehicle/wheel.json @@ -101750,7 +101992,7 @@ msgstr "一個簡單的金屬輪子。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "rail wheel" msgid_plural "rail wheels" -msgstr[0] "" +msgstr[0] "轨道轮" #. ~ Description for {'str': 'rail wheel'} #: data/json/items/vehicle/wheel.json @@ -101762,7 +102004,7 @@ msgstr "堅固的軌道用輪胎。有著適合在軌道上運行的輪緣,但 #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "pair of small rail wheels" msgid_plural "pairs of small rail wheels" -msgstr[0] "" +msgstr[0] "窄轨轨道轮" #. ~ Description for {'str': 'pair of small rail wheels', 'str_pl': 'pairs of #. small rail wheels'} @@ -101775,7 +102017,7 @@ msgstr "一对窄轨火车车轮。它适合用在游乐园等地的观光窄轨 #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "motorbike wheel" msgid_plural "motorbike wheels" -msgstr[0] "" +msgstr[0] "摩托车轮" #. ~ Description for {'str': 'motorbike wheel'} #: data/json/items/vehicle/wheel.json @@ -101785,7 +102027,7 @@ msgstr "一個機車輪胎。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "off-road motorbike wheel" msgid_plural "off-road motorbike wheels" -msgstr[0] "" +msgstr[0] "越野摩托车轮" #. ~ Description for {'str': 'off-road motorbike wheel'} #: data/json/items/vehicle/wheel.json @@ -101795,7 +102037,7 @@ msgstr "機車輪胎,以鉚釘增加越野的性能。" #: data/json/items/vehicle/wheel.json msgid "large steel drum" msgid_plural "large steel drums" -msgstr[0] "" +msgstr[0] "大型钢筒" #. ~ Description for {'str': 'large steel drum'} #: data/json/items/vehicle/wheel.json @@ -101809,7 +102051,7 @@ msgstr "一個大型圓筒狀的鋼製滾輪, 通常只會在壓路機上找到, #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "small wheel" msgid_plural "small wheels" -msgstr[0] "" +msgstr[0] "小型车轮" #. ~ Description for {'str': 'small wheel'} #: data/json/items/vehicle/wheel.json @@ -101845,7 +102087,7 @@ msgstr "一對輪椅用的輪胎。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "wide wheel" msgid_plural "wide wheels" -msgstr[0] "" +msgstr[0] "宽车轮" #. ~ Description for {'str': 'wide wheel'} #: data/json/items/vehicle/wheel.json @@ -101855,7 +102097,7 @@ msgstr "一個寬輪胎。大概 \\o/ 這麼寬。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "off-road wide wheel" msgid_plural "off-road wide wheels" -msgstr[0] "" +msgstr[0] "宽越野车轮" #. ~ Description for {'str': 'off-road wide wheel'} #: data/json/items/vehicle/wheel.json @@ -101867,7 +102109,7 @@ msgstr "一個寬的車輪, \\o/ 這樣寬,它上面的飾釘能在越野時 #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "wooden cart wheel" msgid_plural "wooden cart wheels" -msgstr[0] "" +msgstr[0] "木制车轮" #. ~ Description for {'str': 'wooden cart wheel'} #: data/json/items/vehicle/wheel.json @@ -101877,7 +102119,7 @@ msgstr "一個手工製作的木製手推車腳輪。" #: data/json/items/vehicle/wheel.json data/json/vehicleparts/wheel.json msgid "banded wooden cart wheel" msgid_plural "banded wooden cart wheels" -msgstr[0] "" +msgstr[0] "镶边木制车轮" #. ~ Description for {'str': 'banded wooden cart wheel'} #: data/json/items/vehicle/wheel.json @@ -103717,7 +103959,7 @@ msgstr "一個昆蟲外型的機器人,大小跟小狗一樣,設計作為居 #: data/json/monsters/defense_bot.json msgid "experimental lab bot" msgid_plural "experimental lab bots" -msgstr[0] "" +msgstr[0] "实验室原型机器人" #. ~ Description for {'str': 'experimental lab bot'} #: data/json/monsters/defense_bot.json @@ -103745,7 +103987,7 @@ msgstr "" #: data/json/monsters/defense_bot.json msgid "NR-031 Dispatch" msgid_plural "NR-031 Dispatches" -msgstr[0] "" +msgstr[0] "NR-031 派遣者" #. ~ Description for {'str': 'NR-031 Dispatch', 'str_pl': 'NR-031 Dispatches'} #: data/json/monsters/defense_bot.json @@ -103760,7 +104002,7 @@ msgstr "" #: data/json/monsters/defense_bot.json msgid "NR-V05-M Dispatch" msgid_plural "NR-V05-M Dispatches" -msgstr[0] "" +msgstr[0] "NR-V05-M 派遣者" #. ~ Description for {'str': 'NR-V05-M Dispatch', 'str_pl': 'NR-V05-M #. Dispatches'} @@ -104901,7 +105143,7 @@ msgstr "真菌从这只笨重的骷髅巨兽的骨板缝隙中长出,它的眼 #: data/json/monsters/fungus.json data/mods/Limit Fungal Growth/modinfo.json msgid "fungal child" msgid_plural "fungal children" -msgstr[0] "" +msgstr[0] "真菌儿童" #. ~ Description for {'str': 'fungal child', 'str_pl': 'fungal children'} #: data/json/monsters/fungus.json @@ -105485,7 +105727,7 @@ msgstr "這隻黑鼠是一種雜食性動物, 有著黑色毛皮與長長粗粗 #: data/json/monsters/mammal.json msgid "wild boar piglet" msgid_plural "wild boar piglets" -msgstr[0] "" +msgstr[0] "小野猪" #. ~ Description for wild boar piglet #. ~ Description for wild boar @@ -105501,7 +105743,7 @@ msgstr "" #: data/json/monsters/mammal.json msgid "wild boar" msgid_plural "wild boars" -msgstr[0] "" +msgstr[0] "野猪" #: data/json/monsters/mammal.json msgid "bobcat" @@ -105518,7 +105760,7 @@ msgstr "一种生活在北美大部分地区的斑点野猫。它对人类而言 #: data/json/monsters/mammal.json msgid "shorthair kitten" msgid_plural "shorthair kittens" -msgstr[0] "" +msgstr[0] "短毛幼猫" #. ~ Description for {'str': 'shorthair kitten'} #: data/json/monsters/mammal.json @@ -105529,7 +105771,7 @@ msgstr "一只可爱的小猫,喵喵叫着在死亡的夹缝间流窜。看上 #: data/json/monsters/mammal.json msgid "shorthair cat" msgid_plural "shorthair cats" -msgstr[0] "" +msgstr[0] "短毛猫" #. ~ Description for {'str': 'shorthair cat'} #: data/json/monsters/mammal.json @@ -105542,7 +105784,7 @@ msgstr "恢復野性的小型食肉獵食動物。受到了生存的嚴重考驗 #: data/json/monsters/mammal.json msgid "longhair cat" msgid_plural "longhair cats" -msgstr[0] "" +msgstr[0] "长毛猫" #. ~ Description for longhair cat #: data/json/monsters/mammal.json @@ -105554,7 +105796,7 @@ msgstr "这只猫的长毛看起来很难梳理,但是在目前环境下它似 #: data/json/monsters/mammal.json msgid "longhair kitten" msgid_plural "longhair kittens" -msgstr[0] "" +msgstr[0] "长毛幼猫" #. ~ Description for longhair kitten #: data/json/monsters/mammal.json @@ -105566,7 +105808,7 @@ msgstr "虽然看起来不过是一团长着眼睛的小毛球,但这只小猫 #: data/json/monsters/mammal.json msgid "Maine coon cat" msgid_plural "Maine coon cats" -msgstr[0] "" +msgstr[0] "缅因库恩猫" #. ~ Description for Maine coon cat #: data/json/monsters/mammal.json @@ -105578,7 +105820,7 @@ msgstr "按家猫的标准来说,它的体型十分大,令人印象深刻, #: data/json/monsters/mammal.json msgid "Maine coon kitten" msgid_plural "Maine coon kittens" -msgstr[0] "" +msgstr[0] "缅因库恩幼猫" #. ~ Description for Maine coon kitten #: data/json/monsters/mammal.json @@ -105589,7 +105831,7 @@ msgstr "这只缅因幼猫长着簇生着毛的耳朵,脸上的图案十分醒 #: data/json/monsters/mammal.json msgid "Siamese cat" msgid_plural "Siamese cats" -msgstr[0] "" +msgstr[0] "暹罗猫" #. ~ Description for Siamese cat #: data/json/monsters/mammal.json @@ -105601,7 +105843,7 @@ msgstr "这只猫是一只有着独特纯黑色的暹罗猫,原产于亚洲, #: data/json/monsters/mammal.json msgid "Siamese kitten" msgid_plural "Siamese kittens" -msgstr[0] "" +msgstr[0] "暹罗幼猫" #. ~ Description for Siamese kitten #: data/json/monsters/mammal.json @@ -105613,7 +105855,7 @@ msgstr "有着奶油色的皮毛和深色的斑点,你猜这只小猫一定是 #: data/json/monsters/mammal.json msgid "Persian cat" msgid_plural "Persian cats" -msgstr[0] "" +msgstr[0] "波斯猫" #. ~ Description for Persian cat #: data/json/monsters/mammal.json @@ -105625,7 +105867,7 @@ msgstr "这种猫的短鼻子和圆脸清晰地表明了它属于流行的波斯 #: data/json/monsters/mammal.json msgid "Persian kitten" msgid_plural "Persian kittens" -msgstr[0] "" +msgstr[0] "波斯幼猫" #. ~ Description for Persian kitten #: data/json/monsters/mammal.json @@ -105637,7 +105879,7 @@ msgstr "它可爱的塌鼻子和悲伤恳求的眼神恳求你收留下这只幼 #: data/json/monsters/mammal.json msgid "Bengal cat" msgid_plural "Bengal cats" -msgstr[0] "" +msgstr[0] "孟加拉猫" #. ~ Description for Bengal cat #: data/json/monsters/mammal.json @@ -105649,7 +105891,7 @@ msgstr "看起来像斑点野猫,这只孟加拉猫是亚洲豹猫和埃及猫 #: data/json/monsters/mammal.json msgid "Bengal kitten" msgid_plural "Bengal kittens" -msgstr[0] "" +msgstr[0] "孟加拉幼猫" #. ~ Description for Bengal kitten #: data/json/monsters/mammal.json @@ -105660,7 +105902,7 @@ msgstr "你在孟加拉猫身上见过这样的斑点,但它还只是只小猫 #: data/json/monsters/mammal.json msgid "Devon Rex cat" msgid_plural "Devon Rex cats" -msgstr[0] "" +msgstr[0] "德文雷克斯猫" #. ~ Description for Devon Rex cat #: data/json/monsters/mammal.json @@ -105672,7 +105914,7 @@ msgstr "一只有着惊人的大眼睛和大耳朵的外表奇特的猫,长着 #: data/json/monsters/mammal.json msgid "Devon Rex kitten" msgid_plural "Devon Rex kittens" -msgstr[0] "" +msgstr[0] "德文雷克斯幼猫" #. ~ Description for Devon Rex kitten #: data/json/monsters/mammal.json @@ -105684,7 +105926,7 @@ msgstr "这只长着卷毛的小猫有着巨大的耳朵和好奇的眼睛,可 #: data/json/monsters/mammal.json msgid "Sphynx cat" msgid_plural "Sphynx cats" -msgstr[0] "" +msgstr[0] "斯芬克斯猫" #. ~ Description for Sphynx cat #: data/json/monsters/mammal.json @@ -105696,7 +105938,7 @@ msgstr "这只斯芬克斯猫身上几乎完全不长毛,露出了古怪的皱 #: data/json/monsters/mammal.json msgid "Sphynx kitten" msgid_plural "Sphynx kittens" -msgstr[0] "" +msgstr[0] "斯芬克斯幼猫" #. ~ Description for Sphynx kitten #: data/json/monsters/mammal.json @@ -105708,7 +105950,7 @@ msgstr "这只小猫身上几乎完全没有毛,这说明它是无毛的斯芬 #: data/json/monsters/mammal.json msgid "tabby cat" msgid_plural "tabby cats" -msgstr[0] "" +msgstr[0] "虎斑猫" #. ~ Description for tabby cat #: data/json/monsters/mammal.json @@ -105720,7 +105962,7 @@ msgstr "额头上标志性的\"M\"形花纹和全身包围的条纹,这只猫 #: data/json/monsters/mammal.json msgid "tabby kitten" msgid_plural "tabby kittens" -msgstr[0] "" +msgstr[0] "虎斑幼猫" #. ~ Description for tabby kitten #: data/json/monsters/mammal.json @@ -105732,7 +105974,7 @@ msgstr "眼睛周围的锋利线条和熟悉的波浪状条纹表明这只小猫 #: data/json/monsters/mammal.json msgid "calico cat" msgid_plural "calico cats" -msgstr[0] "" +msgstr[0] "三花猫" #. ~ Description for calico cat #: data/json/monsters/mammal.json @@ -105745,7 +105987,7 @@ msgstr "白色毛发中夹杂了橙色和黑色的斑点,这些特征说明它 #: data/json/monsters/mammal.json msgid "calico kitten" msgid_plural "calico kittens" -msgstr[0] "" +msgstr[0] "三花幼猫" #. ~ Description for calico kitten #: data/json/monsters/mammal.json @@ -105757,7 +105999,7 @@ msgstr "斑驳的棕色和灰色斑点表明了这只小猫是一只三花猫, #: data/json/monsters/mammal.json msgid "golden chonker" msgid_plural "golden chonkers" -msgstr[0] "" +msgstr[0] "金橘胖猫" #. ~ Description for golden chonker #: data/json/monsters/mammal.json @@ -105770,7 +106012,7 @@ msgstr "天哦,它来了!这只令人印象深刻的猫科动物曾经因其 #: data/json/monsters/mammal.json msgid "yellow kitten" msgid_plural "yellow kittens" -msgstr[0] "" +msgstr[0] "黄色幼猫" #. ~ Description for yellow kitten #: data/json/monsters/mammal.json @@ -105811,7 +106053,7 @@ msgstr "" #: data/json/monsters/mammal.json msgid "calf" msgid_plural "calves" -msgstr[0] "" +msgstr[0] "牛犊" #. ~ Description for {'str': 'calf', 'str_pl': 'calves'} #. ~ Description for {'str': 'cow'} @@ -106730,7 +106972,7 @@ msgstr "完全由光組成的影像,與它參照的對象幾乎沒有區別。 #: data/json/monsters/mutant_animal.json msgid "scaled bear" msgid_plural "scaled bears" -msgstr[0] "" +msgstr[0] "鳞甲熊" #. ~ Description for {'str': 'scaled bear'} #: data/json/monsters/mutant_animal.json @@ -106999,7 +107241,7 @@ msgstr "有著黏稠身體的狗, 黑色的觸手從頭部延伸出來。" #: data/json/monsters/nether.json msgid "homunculus" msgid_plural "homunculi" -msgstr[0] "" +msgstr[0] "何蒙库鲁兹" #. ~ Description for {'str': 'homunculus', 'str_pl': 'homunculi'} #: data/json/monsters/nether.json @@ -107162,7 +107404,7 @@ msgstr "空氣中的一個氣流扭曲點, 有某種東西在其中心點。" #: data/json/monsters/power_leech.json msgid "leech blossom" msgid_plural "leech blossoms" -msgstr[0] "" +msgstr[0] "水蛭花" #. ~ Description for {'str': 'leech blossom'} #: data/json/monsters/power_leech.json @@ -107178,7 +107420,7 @@ msgstr "水蛭花射出了一道电弧!" #: data/json/monsters/power_leech.json msgid "leech stalk" msgid_plural "leech stalks" -msgstr[0] "" +msgstr[0] "水蛭花茎秆" #. ~ Description for {'str': 'leech stalk'} #: data/json/monsters/power_leech.json @@ -107195,7 +107437,7 @@ msgstr "水蛭花茎秆射出了一道电弧!" #: data/json/monsters/power_leech.json msgid "signal tree" msgid_plural "signal trees" -msgstr[0] "" +msgstr[0] "信标树" #. ~ Description for signal tree #: data/json/monsters/power_leech.json @@ -107212,7 +107454,7 @@ msgstr "信号树的树枝闪烁并发出耀眼的脉冲!" #: data/json/monsters/power_leech.json msgid "leech pod cluster" msgid_plural "leech pod clusters" -msgstr[0] "" +msgstr[0] "水蛭花苞" #. ~ Description for {'str': 'leech pod cluster'} #: data/json/monsters/power_leech.json @@ -107229,7 +107471,7 @@ msgstr "水蛭花苞射出了一道电弧!" #: data/json/monsters/power_leech.json msgid "root runner" msgid_plural "root runners" -msgstr[0] "" +msgstr[0] "根状追猎者" #. ~ Description for {'str': 'root runner'} #: data/json/monsters/power_leech.json @@ -107249,7 +107491,7 @@ msgstr "根状追猎者射出了一道电弧!" #: data/json/monsters/power_leech.json msgid "root drone" msgid_plural "root drones" -msgstr[0] "" +msgstr[0] "根状工蜂" #. ~ Description for {'str': 'root drone'} #: data/json/monsters/power_leech.json @@ -107328,11 +107570,6 @@ msgid "" "of infesting sewer lines." msgstr "一個攻擊性強的突變蛇, 因地下生活而呈現淡黃色。它的名稱由來是因為它盤據在地底的習性。" -#: data/json/monsters/slimes.json -msgid "blob" -msgid_plural "blobs" -msgstr[0] "黏球怪" - #. ~ Description for {'str': 'blob'} #: data/json/monsters/slimes.json msgid "" @@ -107558,7 +107795,7 @@ msgstr "一個粗壯的木本植物, 能夠挖穿地面並且從它的樹枝射 #: data/json/monsters/triffid.json msgid "triffid flower" msgid_plural "triffid flowers" -msgstr[0] "" +msgstr[0] "三尖树之花" #. ~ Description for {'str': 'triffid flower'} #: data/json/monsters/triffid.json @@ -107612,7 +107849,7 @@ msgstr "這個 TX-5LR 地獄犬槍塔是該系列的新型號。採用了先進 #: data/mods/Generic_Guns/robots/active_bots.json msgid "riot control platform" msgid_plural "riot control platforms" -msgstr[0] "" +msgstr[0] "防暴平台" #. ~ Description for {'str': 'riot control platform'} #: data/json/monsters/turrets.json @@ -107634,7 +107871,7 @@ msgstr "" #: data/mods/Generic_Guns/robots/gg_bots_migration.json msgid "light turret" msgid_plural "light turrets" -msgstr[0] "" +msgstr[0] "轻型炮塔" #. ~ Description for {'str': 'light turret'} #: data/json/monsters/turrets.json @@ -107651,7 +107888,7 @@ msgstr "" #: data/json/monsters/turrets.json msgid "medium milspec turret" msgid_plural "medium milspec turrets" -msgstr[0] "" +msgstr[0] "中型军用炮塔" #. ~ Description for {'str': 'medium milspec turret'} #: data/json/monsters/turrets.json @@ -107667,7 +107904,7 @@ msgstr "" #: data/mods/Generic_Guns/robots/gg_bots_migration.json msgid "longrange milspec turret" msgid_plural "longrange milspec turrets" -msgstr[0] "" +msgstr[0] "长程军用炮塔" #. ~ Description for {'str': 'longrange milspec turret'} #: data/json/monsters/turrets.json @@ -107745,7 +107982,7 @@ msgstr "福特Sanitron, 一個設計用於危險環境下清理廢棄物的實 #: data/json/monsters/utility_bot.json msgid "hauler bot" msgid_plural "hauler bots" -msgstr[0] "" +msgstr[0] "运输机器人" #. ~ Description for {'str': 'hauler bot'} #: data/json/monsters/utility_bot.json @@ -107939,11 +108176,6 @@ msgid "" "envelope of scar tissue." msgstr "一个畸形丧尸,它的皮肤变成了一层厚厚的、带硬壳的疤痕组织。" -#: data/json/monsters/zed-classic.json data/json/npcs/talk_tags.json -msgid "zombie" -msgid_plural "zombies" -msgstr[0] "殭屍" - #. ~ Description for {'str': 'zombie'} #: data/json/monsters/zed-classic.json msgid "" @@ -108047,7 +108279,7 @@ msgstr "一具死過一次的人類屍體。那變色浮腫的肉佈滿了化膿 #: data/json/monsters/zed-classic.json msgid "SWAT zombie" msgid_plural "SWAT zombies" -msgstr[0] "" +msgstr[0] "SWAT丧尸" #. ~ Description for SWAT zombie #: data/json/monsters/zed-classic.json @@ -108071,7 +108303,7 @@ msgstr "曾經是運動員, 現在是個凶暴的怪物。它的五官都扭曲 #: data/json/monsters/zed-classic.json msgid "sleek zombie" msgid_plural "sleek zombies" -msgstr[0] "" +msgstr[0] "时髦丧尸" #. ~ Description for {'str': 'sleek zombie'} #: data/json/monsters/zed-classic.json @@ -108081,7 +108313,7 @@ msgstr "这只丧尸非常时髦并且衣着暴露。" #: data/json/monsters/zed-classic.json msgid "bouncer zombie" msgid_plural "bouncer zombies" -msgstr[0] "" +msgstr[0] "保镖丧尸" #. ~ Description for {'str': 'bouncer zombie'} #: data/json/monsters/zed-classic.json @@ -108135,7 +108367,7 @@ msgstr "這個殭屍的整張臉幾乎被退化成了噴管狀的嘴巴所盤據 #: data/json/monsters/zed_acid.json msgid "wretched puker" msgid_plural "wretched pukers" -msgstr[0] "" +msgstr[0] "可怖呕吐者" #. ~ Description for {'str': 'wretched puker'} #: data/json/monsters/zed_acid.json @@ -108310,7 +108542,7 @@ msgstr "" #: data/json/monsters/zed_electric.json msgid "zapper zombie" msgid_plural "zapper zombies" -msgstr[0] "" +msgstr[0] "静电丧尸" #. ~ Description for {'str': 'zapper zombie'} #: data/json/monsters/zed_electric.json @@ -108407,7 +108639,7 @@ msgstr "由許多人體組織交雜融合在一起的噁心形體, 緩慢的在 #: data/json/monsters/zed_fusion.json msgid "dissoluted devourer" msgid_plural "dissoluted devourers" -msgstr[0] "" +msgstr[0] "放荡吞噬者" #. ~ Description for {'str': 'dissoluted devourer'} #: data/json/monsters/zed_fusion.json @@ -108520,7 +108752,7 @@ msgstr "一只摇摇欲坠的丧尸,穿着灰色制服和前面印有\"保安\ #: data/json/monsters/zed_medical.json msgid "nurse" msgid_plural "nurses" -msgstr[0] "" +msgstr[0] "护士丧尸" #. ~ Description for {'str': 'nurse'} #: data/json/monsters/zed_medical.json @@ -108533,7 +108765,7 @@ msgstr "这只僵尸没有前臂,取而代之的是一根肌肉管,其末端 #: data/json/monsters/zed_medical.json msgid "surgeon" msgid_plural "surgeons" -msgstr[0] "" +msgstr[0] "外科医生丧尸" #. ~ Description for {'str': 'surgeon'} #: data/json/monsters/zed_medical.json @@ -108546,7 +108778,7 @@ msgstr "一只手是一只不断滴下液体的毒刺,另一只手则是一副 #: data/json/monsters/zed_medical.json msgid "vivisector" msgid_plural "vivisectors" -msgstr[0] "" +msgstr[0] "活体解剖者" #. ~ Description for {'str': 'vivisector'} #: data/json/monsters/zed_medical.json @@ -108896,7 +109128,7 @@ msgstr "這隻殭屍仍然穿著工作服還有安全帽, 生前似乎是在電 #: data/json/monsters/zed_misc.json msgid "zombie miner" msgid_plural "zombie miners" -msgstr[0] "" +msgstr[0] "矿工丧尸" #. ~ Description for {'str': 'zombie miner'} #: data/json/monsters/zed_misc.json @@ -109027,7 +109259,7 @@ msgstr "曾經是個軍人, 它現在從頭到腳都穿著戰鬥裝備, 移動 #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json msgid "black-ops zombie" msgid_plural "black-ops zombies" -msgstr[0] "" +msgstr[0] "黑雾丧尸" #. ~ Description for {'str': 'black-ops zombie'} #: data/json/monsters/zed_soldiers.json data/mods/No_Hope/monsters.json @@ -109083,7 +109315,7 @@ msgstr "" #: data/json/monsters/zed_soldiers.json msgid "Kevlar zombie" msgid_plural "Kevlar zombies" -msgstr[0] "" +msgstr[0] "凯夫拉丧尸" #. ~ Description for {'str': 'Kevlar zombie'} #: data/json/monsters/zed_soldiers.json @@ -109100,7 +109332,7 @@ msgstr "" #: data/json/monsters/zed_soldiers.json msgid "Kevlar hulk" msgid_plural "Kevlar hulks" -msgstr[0] "" +msgstr[0] "凯夫拉浩克" #. ~ Description for {'str': 'Kevlar hulk'} #: data/json/monsters/zed_soldiers.json @@ -109169,7 +109401,7 @@ msgstr "這隻武裝、強化過的軍人身上的生化插件發出能量的爆 #: data/json/monsters/zed_soldiers.json msgid "elite zombie bio-operator" msgid_plural "elite zombie bio-operators" -msgstr[0] "" +msgstr[0] "精英生化战士丧尸" #. ~ Description for {'str': 'elite zombie bio-operator'} #: data/json/monsters/zed_soldiers.json @@ -109193,7 +109425,7 @@ msgstr "你清楚地意識到, 這具仍然穿戴著簡易盔甲和支離破碎 #: data/json/monsters/zed_survivor.json msgid "veteran survivor zombie" msgid_plural "veteran survivor zombies" -msgstr[0] "" +msgstr[0] "资深幸存者丧尸" #. ~ Description for {'str': 'veteran survivor zombie'} #: data/json/monsters/zed_survivor.json @@ -118128,7 +118360,8 @@ msgid "I'll kill you if you don't." msgstr "你不照做我就殺了你!" #: data/json/npcs/TALK_COMMON_OTHER.json -#: data/json/npcs/TALK_TRUE_FOODPERSON.json src/iuse.cpp +#: data/json/npcs/TALK_TRUE_FOODPERSON.json +#: data/mods/smart_house_remotes/main.lua src/iuse.cpp msgid "Nevermind." msgstr "沒事。" @@ -126066,10 +126299,6 @@ msgstr "怪活" msgid "demon" msgstr "惡魔" -#: data/json/npcs/talk_tags.json -msgid "horror" -msgstr "恐怖" - #: data/json/npcs/talk_tags.json msgid "indescribable beast" msgstr "無以名狀之獸" @@ -134766,7 +134995,7 @@ msgstr "即便如此,你的努力对我来说也意味着很多。" #: data/json/npcs/refugee_center/surface_refugees/NPC_Boris_Borichenko.json msgid "Ash's laptop computer" msgid_plural "Ash's laptop computers" -msgstr[0] "" +msgstr[0] "阿什的笔记本电脑" #. ~ Description for {'str': "Ash's laptop computer"} #: data/json/npcs/refugee_center/surface_refugees/NPC_Boris_Borichenko.json @@ -135116,7 +135345,7 @@ msgstr "如果没有那罐特别的面团,我想我是挺不过这场大灾变 #: data/json/npcs/refugee_center/surface_refugees/NPC_Dana_Nunez.json msgid "Dana's family sourdough starter" msgid_plural "Dana's family sourdough starter" -msgstr[0] "" +msgstr[0] "达娜的家用酸面头" #. ~ Description for {'str_sp': "Dana's family sourdough starter"} #: data/json/npcs/refugee_center/surface_refugees/NPC_Dana_Nunez.json @@ -135132,7 +135361,7 @@ msgstr "" #: data/json/npcs/refugee_center/surface_refugees/NPC_Dana_Nunez.json msgid "Dana's sourdough bread" msgid_plural "Dana's sourdough breads" -msgstr[0] "" +msgstr[0] "达娜的酸面包" #. ~ Description for {'str': "Dana's sourdough bread"} #: data/json/npcs/refugee_center/surface_refugees/NPC_Dana_Nunez.json @@ -139891,6 +140120,16 @@ msgid "" "coming no further. Go away." msgstr "等一下。我不在乎你是怎麼進來這裡的,但是你不能再前進了。快離開。" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"I was sent here by the traders at the refugee center. They told me to " +"deliver this hard drive to you." +msgstr "我是被避难中心的商贩派来的。他们告诉我要把这个硬盘送给您。" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "The traders also mentioned you were looking for help." +msgstr "商贩还提到您正在寻找帮助。" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "Wait! What??" msgstr "等等!什么??" @@ -139927,6 +140166,20 @@ msgstr "那麼,關於那個防護裝備?" msgid "Alright, I'm leaving." msgstr "好吧,我要走了。" +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "" +"Understood. Please drop the drive on the box embedded beneath the intercom." +" You are welcome to leave afterwards." +msgstr "明白了。请将硬盘放在对讲机下嵌入的盒子里。之后您可以离开。" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "[Do as the Intercom Says]" +msgstr "[按对讲机的指示行事]" + +#: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json +msgid "Didn't bring the hard drive now, let me return with it." +msgstr "现在没有带硬盘,我会带着它回来。" + #: data/json/npcs/robofac/NPC_ROBOFAC_INTERCOM.json msgid "No. Now leave." msgstr "不,現在離開。" @@ -142468,7 +142721,7 @@ msgstr "小型的流浪汉火炉,用金属罐或大小合适的类似容器制 #: data/json/obsoletion/items.json msgid "40mm flare" msgid_plural "40mm flares" -msgstr[0] "" +msgstr[0] "40x46mm M583 照明弹" #. ~ Description for {'str': '40mm flare'} #: data/json/obsoletion/items.json @@ -142480,7 +142733,7 @@ msgstr "一個 40mm 口徑的信號彈, 能夠暫時照亮四周一陣子, 但 #: data/json/obsoletion/items.json msgid "40x46mm" msgid_plural "40x46mms" -msgstr[0] "" +msgstr[0] "40x46mm M585 闪光弹" #. ~ Description for {'str': '40x46mm'} #: data/json/obsoletion/items.json @@ -142504,7 +142757,7 @@ msgstr "內含固態汽油, 能夠產生燃燒效果的 40mm 榴彈。" #: data/json/obsoletion/items.json msgid "40mm smoke cover" msgid_plural "40mm smoke covers" -msgstr[0] "" +msgstr[0] "40x46mm M680 烟雾弹" #. ~ Description for {'str': '40mm smoke cover'} #: data/json/obsoletion/items.json @@ -142514,7 +142767,7 @@ msgstr "40mm 的煙霧榴彈, 用來提供煙霧掩護。" #: data/json/obsoletion/items.json msgid "40mm slug" msgid_plural "40mm slugs" -msgstr[0] "" +msgstr[0] "40mm 独头弹" #. ~ Description for {'str': '40mm slug'} #: data/json/obsoletion/items.json @@ -142661,7 +142914,7 @@ msgstr "" #: data/mods/No_Hope/Items/generic.json msgid "broken chickenbot" msgid_plural "broken chickenbots" -msgstr[0] "" +msgstr[0] "双足机器人(损坏)" #. ~ Use action friendly_msg for {'str': 'broken chickenbot'}. #. ~ Use action friendly_msg for {'str': 'inactive chicken walker'}. @@ -142699,7 +142952,7 @@ msgstr "一个损坏的双足机器人。可能因为巨大的体积和质量的 #: data/mods/No_Hope/Items/tools.json msgid "inactive tripod" msgid_plural "inactive tripods" -msgstr[0] "" +msgstr[0] "三足机器人(关)" #. ~ Use action friendly_msg for {'str': 'inactive tripod'}. #. ~ Use action friendly_msg for inactive tripod. @@ -143271,7 +143524,7 @@ msgstr "" #: data/mods/No_Hope/Items/magazines.json msgid "LW-5 speedloader" msgid_plural "LW-5 speedloaders" -msgstr[0] "" +msgstr[0] "LW-5 快速装弹器" #. ~ Description for {'str': 'LW-5 speedloader'} #: data/json/obsoletion/items.json data/mods/No_Hope/Items/magazines.json @@ -143327,7 +143580,7 @@ msgstr "這把手工打造的小型火焰噴射器能夠掛載於幾乎所有槍 #: data/json/obsoletion/items.json msgid "RDX sand bomb" msgid_plural "RDX sand bombs" -msgstr[0] "" +msgstr[0] "RDX沙弹" #. ~ Use action msg for {'str': 'RDX sand bomb'}. #: data/json/obsoletion/items.json @@ -143345,7 +143598,7 @@ msgstr "这是根装着RDX和沙子的钢管。前者推动后者,形成致命 #: data/json/obsoletion/items.json msgid "active RDX sand bomb" msgid_plural "active RDX sand bombs" -msgstr[0] "" +msgstr[0] "RDX沙弹(点燃)" #. ~ Description for {'str': 'active RDX sand bomb'} #: data/json/obsoletion/items.json @@ -143470,7 +143723,7 @@ msgstr "半自動" #: data/json/obsoletion/items.json msgid "nail rifle magazine" msgid_plural "nail rifle magazines" -msgstr[0] "" +msgstr[0] "射钉步枪弹匣" #. ~ Description for {'str': 'nail rifle magazine'} #: data/json/obsoletion/items.json @@ -143483,7 +143736,7 @@ msgstr "一個簡易的彈匣供鐵釘步槍使用。錫罐、彈簧與大力膠 #: data/json/obsoletion/items.json msgid "238-NK: Practicality Enhancement" msgid_plural "copies of 238-NK: Practicality Enhancement" -msgstr[0] "" +msgstr[0] "238-NK:实用性强化" #. ~ Description for {'str': '238-NK: Practicality Enhancement', 'str_pl': #. 'copies of 238-NK: Practicality Enhancement'} @@ -143497,7 +143750,7 @@ msgstr "作者紀錄了非常完整的研究文件, 用一種非常有說服力 #: data/json/obsoletion/items.json msgid "modified mininuke" msgid_plural "modified mininukes" -msgstr[0] "" +msgstr[0] "改装微型核弹" #. ~ Description for {'str': 'modified mininuke'} #: data/json/obsoletion/items.json @@ -143513,7 +143766,7 @@ msgstr "" #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "scrap shotcanister" msgid_plural "scrap shotcanisters" -msgstr[0] "" +msgstr[0] "废料纸壳霰弹" #. ~ Description for {'str': 'scrap shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -143525,7 +143778,7 @@ msgstr "这个形似粗制霰弹的小纸筒填满了各种废金属片……" #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "pebble shotcanister" msgid_plural "pebble shotcanisters" -msgstr[0] "" +msgstr[0] "碎石纸壳霰弹" #. ~ Description for {'str': 'pebble shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -143538,7 +143791,7 @@ msgstr "这个形似粗制霰弹的小纸筒填满了微小的石子。伤害比 #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "flechette shotcanister" msgid_plural "flechette shotcanisters" -msgstr[0] "" +msgstr[0] "镖形纸壳霰弹" #. ~ Description for {'str': 'flechette shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -143550,7 +143803,7 @@ msgstr "这个形似粗制霰弹的小纸筒填满了手工制造的飞镖,这 #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json msgid "bearing shotcanister" msgid_plural "bearing shotcanisters" -msgstr[0] "" +msgstr[0] "滚珠纸壳霰弹" #. ~ Description for {'str': 'bearing shotcanister'} #: data/json/obsoletion/items.json data/mods/No_Hope/Ammo/ammo.json @@ -143566,7 +143819,7 @@ msgstr "射彈罐" #: data/json/obsoletion/items.json msgid "fitness band" msgid_plural "fitness bands" -msgstr[0] "" +msgstr[0] "健身手环" #. ~ Description for fitness band #: data/json/obsoletion/items.json @@ -143640,7 +143893,7 @@ msgstr "玻璃餐盘,适合没有笨拙孩子的人。" #: data/json/obsoletion/items.json msgid "plastic plate" msgid_plural "plastic plates" -msgstr[0] "" +msgstr[0] "塑料盘" #. ~ Description for {'str': 'plastic plate'} #: data/json/obsoletion/items.json @@ -143905,7 +144158,7 @@ msgstr "一块大块扁平的木头,用于切碎蔬菜而不会毁坏你的刀 #: data/json/obsoletion/items.json msgid "meal tray" msgid_plural "meal trays" -msgstr[0] "" +msgstr[0] "供餐托盘" #. ~ Description for {'str': 'meal tray'} #: data/json/obsoletion/items.json @@ -143939,7 +144192,7 @@ msgstr "塑料一次性勺子。比金属品更容易弯曲。" #: data/json/obsoletion/items.json msgid "kiddie spoon" msgid_plural "kiddie spoons" -msgstr[0] "" +msgstr[0] "儿童勺子" #. ~ Description for {'str': 'kiddie spoon'} #: data/json/obsoletion/items.json @@ -143986,7 +144239,7 @@ msgstr "塑料黄油刀。它实际上比它的金属对应物更锐利,但这 #: data/json/obsoletion/items.json msgid "plastic straw" msgid_plural "plastic straws" -msgstr[0] "" +msgstr[0] "塑料吸管" #. ~ Description for {'str': 'plastic straw'} #: data/json/obsoletion/items.json @@ -144009,7 +144262,7 @@ msgstr "坚硬的硬木,转动和打磨光滑,两端带圆形手柄。这款 #: data/json/obsoletion/items.json msgid "badminton shuttlecock" msgid_plural "shuttlecocks" -msgstr[0] "" +msgstr[0] "羽毛球" #. ~ Description for {'str': 'badminton shuttlecock', 'str_pl': #. 'shuttlecocks'} @@ -144098,7 +144351,7 @@ msgstr "一顆高品質室內籃球, 你可以拿來丟殭屍。" #: data/json/obsoletion/items.json msgid "volleyball" msgid_plural "volleyballs" -msgstr[0] "" +msgstr[0] "排球" #. ~ Description for {'str': 'volleyball'} #: data/json/obsoletion/items.json @@ -144108,7 +144361,7 @@ msgstr "一个符合标准规则的排球。" #: data/json/obsoletion/items.json msgid "beach volleyball" msgid_plural "volleyballs" -msgstr[0] "" +msgstr[0] "排球" #. ~ Description for {'str': 'beach volleyball', 'str_pl': 'volleyballs'} #: data/json/obsoletion/items.json @@ -144154,7 +144407,7 @@ msgstr "別偷笑了。這是一個很小的塑膠閥,別想些有的沒的。 #: data/json/obsoletion/items.json msgid "empty ballistic vest" msgid_plural "empty ballistic vests" -msgstr[0] "" +msgstr[0] "防弹背心(空)" #. ~ Description for {'str': 'empty ballistic vest'} #: data/json/obsoletion/items.json @@ -144166,7 +144419,7 @@ msgstr "没有插入装甲板的防弹背心。软质装甲板袋依旧能够提 #: data/json/obsoletion/items.json msgid "ESAPI ballistic vest" msgid_plural "ESAPI ballistic vests" -msgstr[0] "" +msgstr[0] "防弹背心(ESAPI)" #. ~ Description for {'str': 'ESAPI ballistic vest'} #: data/json/obsoletion/items.json @@ -144176,7 +144429,7 @@ msgstr "带有ESAPI陶瓷装甲板的防弹衣。" #: data/json/obsoletion/items.json msgid "ESAPI ballistic plate" msgid_plural "ESAPI ballistic plates" -msgstr[0] "" +msgstr[0] "ESAPI 防弹板" #. ~ Description for {'str': 'ESAPI ballistic plate'} #: data/json/obsoletion/items.json @@ -144192,7 +144445,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "ESBI ballistic plate" msgid_plural "ESBI ballistic plates" -msgstr[0] "" +msgstr[0] "ESBI 防弹板" #. ~ Description for {'str': 'ESBI ballistic plate'} #: data/json/obsoletion/items.json @@ -144232,7 +144485,7 @@ msgstr "這是一種化學發熱貼。能用於治療運動損傷和加熱食物 #: data/json/obsoletion/items.json msgid "inactive autonomous M249 CROWS II" msgid_plural "inactive autonomous M249 CROWS II turrets" -msgstr[0] "" +msgstr[0] "M249 CROWS II 炮塔(关)" #. ~ Description for {'str': 'inactive autonomous M249 CROWS II', 'str_pl': #. 'inactive autonomous M249 CROWS II turrets'} @@ -144252,7 +144505,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "inactive autonomous M240 CROWS II" msgid_plural "inactive autonomous M240 CROWS II turrets" -msgstr[0] "" +msgstr[0] "M240 CROWS II 炮塔(关)" #. ~ Description for {'str': 'inactive autonomous M240 CROWS II', 'str_pl': #. 'inactive autonomous M240 CROWS II turrets'} @@ -144272,7 +144525,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "inactive M2HB autonomous CROWS II" msgid_plural "inactive M2HB autonomous CROWS II turrets" -msgstr[0] "" +msgstr[0] "M2HB CROWS II 炮塔(关)" #. ~ Description for {'str': 'inactive M2HB autonomous CROWS II', 'str_pl': #. 'inactive M2HB autonomous CROWS II turrets'} @@ -144292,17 +144545,17 @@ msgstr "" #: data/json/obsoletion/items.json msgid "broken M249 autonomous CROWS II" msgid_plural "broken M249 autonomous CROWS II turrets" -msgstr[0] "" +msgstr[0] "M249 CROWS II 炮塔(损坏)" #: data/json/obsoletion/items.json msgid "broken M240 autonomous CROWS II" msgid_plural "broken M240 autonomous CROWS II turrets" -msgstr[0] "" +msgstr[0] "M240 CROWS II 炮塔(损坏)" #: data/json/obsoletion/items.json msgid "broken M2 autonomous CROWS II" msgid_plural "broken M2 autonomous CROWS II turrets" -msgstr[0] "" +msgstr[0] "M2HB CROWS II 炮塔(损坏)" #: data/json/obsoletion/items.json #: data/mods/Generic_Guns/robots/inactive_bots.json @@ -144327,7 +144580,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".22 CB" msgid_plural ".22 CBs" -msgstr[0] "" +msgstr[0] ".22 CB弹" #. ~ Description for {'str': '.22 CB'} #: data/json/obsoletion/items.json @@ -144377,7 +144630,7 @@ msgstr "這塊鋼鐵的一邊被捶打成類似斧刃般的鋒利。它能當作 #: data/json/obsoletion/items.json msgid "wooden shed stick" msgid_plural "wooden shed sticks" -msgstr[0] "" +msgstr[0] "木制分纱杆" #. ~ Description for {'str': 'wooden shed stick'} #: data/json/obsoletion/items.json @@ -144418,7 +144671,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "rubber sole" msgid_plural "rubber soles" -msgstr[0] "" +msgstr[0] "橡胶鞋底" #. ~ Description for {'str': 'rubber sole'} #: data/json/obsoletion/items.json @@ -144430,7 +144683,7 @@ msgstr "由橡膠製成的鞋底,通常能在靴子的底部找到。可用於 #: data/json/obsoletion/items.json msgid "tÖttchen" msgid_plural "tÖttchens" -msgstr[0] "" +msgstr[0] "明斯特炖杂碎" #: data/json/obsoletion/items.json msgid "glycerol" @@ -144486,7 +144739,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "microwave generator" msgid_plural "microwave generators" -msgstr[0] "" +msgstr[0] "磁控管" #. ~ Description for {'str': 'microwave generator'} #: data/json/obsoletion/items.json @@ -144498,7 +144751,7 @@ msgstr "一个能够产生微波的电子元件,主要用于微波炉中。" #: data/json/obsoletion/items.json msgid "explosively pumped flux compression generator" msgid_plural "explosively pumped flux compression generators" -msgstr[0] "" +msgstr[0] "爆磁压缩发生器" #. ~ Description for {'str': 'explosively pumped flux compression generator'} #: data/json/obsoletion/items.json @@ -144604,7 +144857,7 @@ msgstr "一張折疊的皮革, 經由仔細地鞣製動物生皮而來, 外毛 #: data/json/obsoletion/items.json msgid "curdling milk" msgid_plural "curdling milks" -msgstr[0] "" +msgstr[0] "凝乳" #. ~ Description for curdling milk #: data/json/obsoletion/items.json @@ -144616,7 +144869,7 @@ msgstr "加了天然凝乳酶的牛奶。若在发酵瓮里放一段时间,就 #: data/json/obsoletion/items.json msgid "curdled milk" msgid_plural "curdled milks" -msgstr[0] "" +msgstr[0] "酪乳" #. ~ Description for curdled milk #: data/json/obsoletion/items.json @@ -144650,7 +144903,7 @@ msgstr "將生牛乳靜置一段時間之後,浮升到頂層的脂肪。" #: data/json/obsoletion/items.json msgid "milk cream jar" msgid_plural "milk cream jars" -msgstr[0] "" +msgstr[0] "奶油罐" #. ~ Description for {'str': 'milk cream jar'} #: data/json/obsoletion/items.json @@ -144662,7 +144915,7 @@ msgstr "这个大罐储存了分离成奶油的生牛奶。封装后可长期储 #: data/json/obsoletion/items.json msgid "rising cream jar" msgid_plural "rising cream jars" -msgstr[0] "" +msgstr[0] "奶油罐(分离中)" #. ~ Use action msg for {'str': 'rising cream jar'}. #: data/json/obsoletion/items.json @@ -144686,7 +144939,7 @@ msgstr "这个大罐储存了准备分离奶油的生牛奶。你可在分离完 #: data/json/obsoletion/items.json msgid "5x50mm flechette, reloaded" msgid_plural "5x50mm flechette, reloadeds" -msgstr[0] "" +msgstr[0] "5x50mm 镖形弹(复装)" #. ~ Description for {'str': '5x50mm flechette, reloaded'} #: data/json/obsoletion/items.json @@ -144699,27 +144952,27 @@ msgstr "用來對付現代身體護甲的子彈, Rivtech 5x50mm 鋼鏢彈有著 #: data/json/obsoletion/items.json msgid "9x19mm JHP, reloaded" msgid_plural "9x19mm JHP, reloadeds" -msgstr[0] "" +msgstr[0] "9x19mm 空尖弹(复装)" #: data/json/obsoletion/items.json msgid "9x19mm FMJ, reloaded" msgid_plural "9x19mm FMJ, reloadeds" -msgstr[0] "" +msgstr[0] "9x19mm 被甲弹(复装)" #: data/json/obsoletion/items.json msgid "9x19mm +P, reloaded" msgid_plural "9x19mm +P, reloadeds" -msgstr[0] "" +msgstr[0] "9x19mm +P 弹(复装)" #: data/json/obsoletion/items.json msgid "9x19mm +P+, reloaded" msgid_plural "9x19mm +P+, reloadeds" -msgstr[0] "" +msgstr[0] "9x19mm +P+ 弹(复装)" #: data/json/obsoletion/items.json msgid "9x18mm, reloaded" msgid_plural "9x18mm, reloadeds" -msgstr[0] "" +msgstr[0] "9x18mm 弹(复装)" #. ~ Description for {'str': '9x18mm, reloaded'} #: data/json/obsoletion/items.json @@ -144732,7 +144985,7 @@ msgstr "9x18mm 馬卡洛夫子彈, 蘇聯舊日的手槍彈種, 主要供馬卡 #: data/json/obsoletion/items.json msgid "9x18mm +P+, reloaded" msgid_plural "9x18mm +P+, reloadeds" -msgstr[0] "" +msgstr[0] "9x18mm +P+ 弹(复装)" #. ~ Description for {'str': '9x18mm +P+, reloaded'} #: data/json/obsoletion/items.json @@ -144746,7 +144999,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "9x18mm FMJ, reloaded" msgid_plural "9x18mm FMJ, reloadeds" -msgstr[0] "" +msgstr[0] "9x18mm 被甲弹(复装)" #. ~ Description for {'str': '9x18mm FMJ, reloaded'} #: data/json/obsoletion/items.json @@ -144761,92 +145014,92 @@ msgstr "" #: data/json/obsoletion/items.json msgid "10mm Auto FMJ, reloaded" msgid_plural "10mm Auto FMJ, reloadeds" -msgstr[0] "" +msgstr[0] "10mm Auto 被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".22 LR, reloaded" msgid_plural ".22 LR, reloadeds" -msgstr[0] "" +msgstr[0] ".22 LR 弹(复装)" #: data/json/obsoletion/items.json msgid ".22 CPHP, reloaded" msgid_plural ".22 CPHP, reloadeds" -msgstr[0] "" +msgstr[0] ".22 镀铜空尖弹(复装)" #: data/json/obsoletion/items.json msgid ".32 ACP, reloaded" msgid_plural ".32 ACP, reloadeds" -msgstr[0] "" +msgstr[0] ".32 ACP 弹(复装)" #: data/json/obsoletion/items.json msgid ".38 FMJ, reloaded" msgid_plural ".38 FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".38 被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".38 Special, reloaded" msgid_plural ".38 Special, reloadeds" -msgstr[0] "" +msgstr[0] ".38 特制弹(复装)" #: data/json/obsoletion/items.json msgid ".38 Super FMJ, reloaded" msgid_plural ".38 Super FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".38 超级被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".38 Super, reloaded" msgid_plural ".38 Super, reloadeds" -msgstr[0] "" +msgstr[0] ".38 超级弹(复装)" #: data/json/obsoletion/items.json msgid ".40 S&W FMJ, reloaded" msgid_plural ".40 S&W FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".40 S&W 被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".40 S&W JHP, reloaded" msgid_plural ".40 S&W JHP, reloadeds" -msgstr[0] "" +msgstr[0] ".40 S&W 空尖弹(复装)" #: data/json/obsoletion/items.json msgid ".44 Magnum FMJ, reloaded" msgid_plural ".44 Magnum FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".44 马格南被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".44 Magnum, reloaded" msgid_plural ".44 Magnum, reloadeds" -msgstr[0] "" +msgstr[0] ".44 马格南弹(复装)" #: data/json/obsoletion/items.json msgid ".45 FMJ, reloaded" msgid_plural ".45 FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".45 ACP 被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".45 ACP JHP, reloaded" msgid_plural ".45 ACP JHP, reloadeds" -msgstr[0] "" +msgstr[0] ".45 ACP 空尖弹(复装)" #: data/json/obsoletion/items.json msgid ".45 ACP +P, reloaded" msgid_plural ".45 ACP +P, reloadeds" -msgstr[0] "" +msgstr[0] ".45 ACP +P弹(复装)" #: data/json/obsoletion/items.json msgid ".45 Colt JHP, reloaded" msgid_plural ".45 Colt JHP, reloadeds" -msgstr[0] "" +msgstr[0] ".45 柯尔特空尖弹(复装)" #: data/json/obsoletion/items.json msgid "4.6x30mm, reloaded" msgid_plural "4.6x30mm, reloadeds" -msgstr[0] "" +msgstr[0] "4.6x30mm 弹(复装)" #: data/json/obsoletion/items.json msgid ".50 BMG tracer, reloaded" msgid_plural ".50 BMG tracer, reloadeds" -msgstr[0] "" +msgstr[0] ".50 BMG 曳光弹(复装)" #. ~ Description for {'str': '.50 BMG tracer, reloaded'} #: data/json/obsoletion/items.json @@ -144859,7 +145112,7 @@ msgstr ".50 BMG 弹的曳光弹型号。曳光弹种可帮助保持对射击目 #: data/json/obsoletion/items.json msgid ".50 BMG Match, reloaded" msgid_plural ".50 BMG Match, reloadeds" -msgstr[0] "" +msgstr[0] ".50 BMG 竞赛弹(复装)" #. ~ Description for {'str': '.50 BMG Match, reloaded'} #: data/json/obsoletion/items.json @@ -144876,7 +145129,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".50 BMG AP, reloaded" msgid_plural ".50 BMG AP, reloadeds" -msgstr[0] "" +msgstr[0] ".50 BMG 穿甲弹(复装)" #. ~ Description for {'str': '.50 BMG AP, reloaded'} #: data/json/obsoletion/items.json @@ -144888,7 +145141,7 @@ msgstr ".50 BMG 彈藥的一種變體,使用的是硬化鋼彈芯。穿透力 #: data/json/obsoletion/items.json msgid "5.7x28mm, reloaded" msgid_plural "5.7x28mm, reloadeds" -msgstr[0] "" +msgstr[0] "5.7x28mm 弹(复装)" #: data/json/obsoletion/items.json msgid "5.56x45mm '.223 Remington', reloaded" @@ -144908,12 +145161,12 @@ msgstr[0] "5.56x45mm NATO 曳光弹(复装)" #: data/json/obsoletion/items.json msgid ".270 Winchester JSP, reloaded" msgid_plural ".270 Winchester JSP, reloadeds" -msgstr[0] "" +msgstr[0] ".270 温彻斯特软尖弹(复装)" #: data/json/obsoletion/items.json msgid ".300 Winchester Magnum, reloaded" msgid_plural ".300 Winchester Magnum, reloadeds" -msgstr[0] "" +msgstr[0] ".300 温彻斯特马格南弹(复装)" #. ~ Description for {'str': '.300 Winchester Magnum, reloaded'} #: data/json/obsoletion/items.json @@ -144926,7 +145179,7 @@ msgstr ".300 溫徹斯特麥格農是一種在許多射擊訓練時廣泛使用 #: data/json/obsoletion/items.json msgid ".300 AAC Blackout, reloaded" msgid_plural ".300 AAC Blackout, reloadeds" -msgstr[0] "" +msgstr[0] ".300 BLK 弹(复装)" #. ~ Description for {'str': '.300 AAC Blackout, reloaded'} #: data/json/obsoletion/items.json @@ -144948,62 +145201,62 @@ msgstr[0] "7.62x51mm '.308 温彻斯特弹'(复装)" #: data/json/obsoletion/items.json msgid "7.62x51mm, reloaded" msgid_plural "7.62x51mm, reloadeds" -msgstr[0] "" +msgstr[0] "7.62x51mm 弹(复装)" #: data/json/obsoletion/items.json msgid "7.62x51mm incendiary, reloaded" msgid_plural "7.62x51mm incendiary, reloadeds" -msgstr[0] "" +msgstr[0] "7.62x51mm 燃烧弹(复装)" #: data/json/obsoletion/items.json msgid ".357 Magnum FMJ, reloaded" msgid_plural ".357 Magnum FMJ, reloaded" -msgstr[0] "" +msgstr[0] ".357 马格南被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".357 Magnum JHP, reloaded" msgid_plural ".357 Magnum JHP, reloaded" -msgstr[0] "" +msgstr[0] ".357 马格南空尖弹(复装)" #: data/json/obsoletion/items.json msgid ".357 SIG FMJ, reloaded" msgid_plural ".357 SIG FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".357 西格被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".357 SIG JHP, reloaded" msgid_plural ".357 SIG JHP, reloadeds" -msgstr[0] "" +msgstr[0] ".357 西格空尖弹(复装)" #: data/json/obsoletion/items.json msgid ".380 ACP FMJ, reloaded" msgid_plural ".380 ACP FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".380 ACP 被甲弹(复装)" #: data/json/obsoletion/items.json msgid ".380 ACP JHP, reloaded" msgid_plural ".380 ACP JHP, reloadeds" -msgstr[0] "" +msgstr[0] ".380 ACP 空尖弹(复装)" #: data/json/obsoletion/items.json msgid ".380 ACP +P, reloaded" msgid_plural ".380 ACP +P, reloadeds" -msgstr[0] "" +msgstr[0] ".380 ACP +P弹(复装)" #: data/json/obsoletion/items.json msgid ".410 000 shot, reloaded" msgid_plural ".410 000 shot, reloadeds" -msgstr[0] "" +msgstr[0] ".410 000 号霰弹(复装)" #: data/json/obsoletion/items.json msgid ".454 Casull, reloaded" msgid_plural ".454 Casull, reloadeds" -msgstr[0] "" +msgstr[0] ".454 卡尔苏弹(复装)" #: data/json/obsoletion/items.json msgid ".460 Rowland FMJ, reloaded" msgid_plural ".460 Rowland FMJ, reloadeds" -msgstr[0] "" +msgstr[0] ".460 罗兰德被甲弹(复装)" #. ~ Description for {'str': '.460 Rowland FMJ, reloaded'} #: data/json/obsoletion/items.json @@ -145015,17 +145268,17 @@ msgstr "以黃銅包覆全顆彈頭的.460羅蘭彈。藉由犧牲彈頭擴張 #: data/json/obsoletion/items.json msgid ".460 Rowland, reloaded" msgid_plural ".460 Rowland, reloadeds" -msgstr[0] "" +msgstr[0] ".460 罗兰德弹(复装)" #: data/json/obsoletion/items.json msgid ".500 S&W Magnum, reloaded" msgid_plural ".500 S&W Magnum, reloadeds" -msgstr[0] "" +msgstr[0] ".500 S&W 马格南弹(复装)" #: data/json/obsoletion/items.json msgid "5.45x39mm, reloaded" msgid_plural "5.45x39mm, reloadeds" -msgstr[0] "" +msgstr[0] "5.45x39mm 弹(复装)" #. ~ Description for {'str': '5.45x39mm, reloaded'} #: data/json/obsoletion/items.json @@ -145040,7 +145293,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "5.45x39mm AP, reloaded" msgid_plural "5.45x39mm AP, reloadeds" -msgstr[0] "" +msgstr[0] "5.45x39mm 穿甲弹(复装)" #. ~ Description for {'str': '5.45x39mm AP, reloaded'} #: data/json/obsoletion/items.json @@ -145052,12 +145305,12 @@ msgstr "5.45x39mm 7N22 手工裝填子彈, 使用配以鋼頭的 57 格令穿甲 #: data/json/obsoletion/items.json msgid ".700 NX, reloaded" msgid_plural ".700 NX, reloadeds" -msgstr[0] "" +msgstr[0] ".700 NX 弹(复装)" #: data/json/obsoletion/items.json msgid "7.62x39mm M43, reloaded" msgid_plural "7.62x39mm M43, reloadeds" -msgstr[0] "" +msgstr[0] "7.62x39mm M43 弹(复装)" #. ~ Description for {'str': '7.62x39mm M43, reloaded'} #: data/json/obsoletion/items.json @@ -145073,37 +145326,37 @@ msgstr "" #: data/json/obsoletion/items.json msgid "7.62x39mm M67, reloaded" msgid_plural "7.62x39mm M67, reloadeds" -msgstr[0] "" +msgstr[0] "7.62x39mm M67 弹(复装)" #: data/json/obsoletion/items.json msgid "7.62x54mmR, reloaded" msgid_plural "7.62x54mmR, reloadeds" -msgstr[0] "" +msgstr[0] "7.62x54mmR 弹(复装)" #: data/json/obsoletion/items.json msgid "7.62x25mm, reloaded" msgid_plural "7.62x25mm, reloadeds" -msgstr[0] "" +msgstr[0] "7.62x25mm 弹(复装)" #: data/json/obsoletion/items.json msgid ".30-06 Springfield, reloaded" msgid_plural ".30-06 Springfield, reloadeds" -msgstr[0] "" +msgstr[0] ".30-06 春田弹(复装)" #: data/json/obsoletion/items.json msgid ".30-06 incendiary, reloaded" msgid_plural ".30-06 incendiary, reloadeds" -msgstr[0] "" +msgstr[0] ".30-06 燃烧弹(复装)" #: data/json/obsoletion/items.json msgid ".30-06 M2 AP, reloaded" msgid_plural ".30-06 M2 AP, reloadeds" -msgstr[0] "" +msgstr[0] ".30-06 M2 穿甲弹(复装)" #: data/json/obsoletion/items.json msgid ".45-70 SP, reloaded" msgid_plural ".45-70 SP, reloadeds" -msgstr[0] "" +msgstr[0] ".45-70 SP弹(复装)" #. ~ Description for {'str': '.45-70 SP, reloaded'} #: data/json/obsoletion/items.json @@ -145117,7 +145370,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".45-70 +P penetrator, reloaded" msgid_plural ".45-70 +P penetrator, reloadeds" -msgstr[0] "" +msgstr[0] ".45-70 +P 穿甲弹(复装)" #. ~ Description for {'str': '.45-70 +P penetrator, reloaded'} #: data/json/obsoletion/items.json @@ -145132,7 +145385,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid ".45-70 LFN cowboy, reloaded" msgid_plural ".45-70 LFN cowboy, reloadeds" -msgstr[0] "" +msgstr[0] ".45-70 LFN 牛仔弹(复装)" #. ~ Description for {'str': '.45-70 LFN cowboy, reloaded'} #: data/json/obsoletion/items.json @@ -145148,32 +145401,32 @@ msgstr "" #: data/json/obsoletion/items.json msgid "birdshot, reloaded" msgid_plural "birdshot, reloadeds" -msgstr[0] "" +msgstr[0] "猎鸟弹(复装)" #: data/json/obsoletion/items.json msgid "dragon's breath shell, reloaded" msgid_plural "dragon's breath shell, reloadeds" -msgstr[0] "" +msgstr[0] "龙息霰弹(复装)" #: data/json/obsoletion/items.json msgid "00 shot, reloaded" msgid_plural "00 shot, reloadeds" -msgstr[0] "" +msgstr[0] "猎鹿弹(复装)" #: data/json/obsoletion/items.json msgid "flechette shell, reloaded" msgid_plural "flechette shell, reloadeds" -msgstr[0] "" +msgstr[0] "镖形霰弹(复装)" #: data/json/obsoletion/items.json msgid "shotgun slug, reloaded" msgid_plural "shotgun slug, reloadeds" -msgstr[0] "" +msgstr[0] "独头霰弹(复装)" #: data/json/obsoletion/items.json msgid "flu shot" msgid_plural "flu shots" -msgstr[0] "" +msgstr[0] "流感疫苗" #. ~ Description for flu shot #: data/json/obsoletion/items.json @@ -145185,7 +145438,7 @@ msgstr "醫藥流感疫苗是設計於大眾接踵疫苗, 聲稱可以提供對 #: data/json/obsoletion/items.json msgid "soap dish" msgid_plural "soap dishes" -msgstr[0] "" +msgstr[0] "肥皂盒" #. ~ Description for {'str': 'soap dish', 'str_pl': 'soap dishes'} #: data/json/obsoletion/items.json @@ -145197,7 +145450,7 @@ msgstr "用来盛肥皂的浅盒子,内部有帮助排水的凸出的脊。这 #: data/json/obsoletion/items.json msgid "toothbrush" msgid_plural "toothbrushes" -msgstr[0] "" +msgstr[0] "牙刷" #. ~ Description for {'str': 'toothbrush', 'str_pl': 'toothbrushes'} #: data/json/obsoletion/items.json @@ -145237,7 +145490,7 @@ msgstr "一根专为儿童设计的短牙刷。手柄上有一辆笑逐颜开的 #: data/json/obsoletion/items.json msgid "hair curler" msgid_plural "hair curlers" -msgstr[0] "" +msgstr[0] "卷发器" #. ~ Description for {'str': 'hair curler'} #: data/json/obsoletion/items.json @@ -145260,7 +145513,7 @@ msgstr "一根用来通管道的带有橡胶头的工具,也是一根新手幸 #: data/json/obsoletion/items.json msgid "professional plunger" msgid_plural "professional plungers" -msgstr[0] "" +msgstr[0] "专业马桶塞" #. ~ Description for {'str': 'professional plunger'} #: data/json/obsoletion/items.json @@ -145272,7 +145525,7 @@ msgstr "一根内部中空的塑料马桶塞,顶部能像手风琴一样压缩 #: data/json/obsoletion/items.json msgid "toilet paper" msgid_plural "rolls of toilet paper" -msgstr[0] "" +msgstr[0] "厕纸" #. ~ Description for {'str': 'toilet paper', 'str_pl': 'rolls of toilet #. paper'} @@ -145324,7 +145577,7 @@ msgstr "殭屍不會害怕這東西或嫌它骯髒,所以這種堅硬的刷子 #: data/json/obsoletion/items.json msgid "Lycra patch" msgid_plural "Lycra patches" -msgstr[0] "" +msgstr[0] "氨纶布片" #. ~ Description for {'str': 'Lycra patch', 'str_pl': 'Lycra patches'} #: data/json/obsoletion/items.json @@ -145337,7 +145590,7 @@ msgstr "一小束掺入了可拉伸的氨纶纤维的合成纤维。可以用来 #: data/json/obsoletion/items.json msgid "Lycra scraps" msgid_plural "Lycra scraps" -msgstr[0] "" +msgstr[0] "氨纶碎片" #. ~ Description for {'str_sp': 'Lycra scraps'} #: data/json/obsoletion/items.json @@ -145349,7 +145602,7 @@ msgstr "形状奇特的小块氨纶面料,某次裁剪产生的废料。没什 #: data/json/obsoletion/items.json msgid "Lycra sheet" msgid_plural "Lycra sheets" -msgstr[0] "" +msgstr[0] "氨纶面料" #. ~ Description for {'str': 'Lycra sheet'} #: data/json/obsoletion/items.json @@ -145361,7 +145614,7 @@ msgstr "一卷掺入了可拉伸的氨纶纤维的合成纤维面料。可以用 #: data/json/obsoletion/items.json msgid "patchwork Lycra clothing parts" msgid_plural "patchwork Lycra clothing parts" -msgstr[0] "" +msgstr[0] "氨纶拼布" #. ~ Description for {'str_sp': 'patchwork Lycra clothing parts'} #: data/json/obsoletion/items.json @@ -145446,7 +145699,7 @@ msgstr "這是一個小盒子,帶有各種各樣的夾子,用於安裝在鐵 #: data/json/obsoletion/items.json msgid "small vacuum oven" msgid_plural "small vacuum ovens" -msgstr[0] "" +msgstr[0] "小型真空炉" #. ~ Description for {'str': 'small vacuum oven'} #: data/json/obsoletion/items.json @@ -145458,7 +145711,7 @@ msgstr "一个体积为0.9立方英尺的小型真空炉,能够清除液体和 #: data/json/obsoletion/items.json msgid "filled small vacuum oven" msgid_plural "filled small vacuum ovens" -msgstr[0] "" +msgstr[0] "小型真空炉(满)" #. ~ Use action msg for {'str': 'filled small vacuum oven'}. #: data/json/obsoletion/items.json @@ -145480,7 +145733,7 @@ msgstr "一个装满了精油的小型真空炉,准备好清除其中残留的 #: data/json/obsoletion/items.json msgid "small vacuum oven (on)" msgid_plural "small vacuum ovens (on)" -msgstr[0] "" +msgstr[0] "小型真空炉(开)" #. ~ Use action msg for {'str': 'small vacuum oven (on)', 'str_pl': 'small #. vacuum ovens (on)'}. @@ -145505,7 +145758,7 @@ msgstr "一个装满了精油的小型真空炉,正在清除其中残留的溶 #: data/json/obsoletion/items.json msgid "finished small vacuum oven" msgid_plural "finished small vacuum ovens" -msgstr[0] "" +msgstr[0] "小型真空炉(完成)" #. ~ Description for {'str': 'finished small vacuum oven'} #: data/json/obsoletion/items.json @@ -145517,7 +145770,7 @@ msgstr "一个装满了精油的小型真空炉,已经完成清除溶剂。喔 #: data/json/obsoletion/items.json msgid "vacuum pump" msgid_plural "vacuum pumps" -msgstr[0] "" +msgstr[0] "真空泵" #. ~ Use action menu_text for {'str': 'vacuum pump'}. #. ~ Use action menu_text for {'str': 'small closed loop extractor'}. @@ -145550,7 +145803,7 @@ msgstr "一台由小型皮带驱动的机械真空泵,能够达到-29.99汞柱 #: data/json/obsoletion/items.json msgid "vacuum pump (on)" msgid_plural "vacuum pumps (on)" -msgstr[0] "" +msgstr[0] "真空泵(开)" #. ~ Use action menu_text for {'str': 'vacuum pump (on)', 'str_pl': 'vacuum #. pumps (on)'}. @@ -145571,7 +145824,7 @@ msgstr "你关闭了真空泵。" #: data/json/obsoletion/items.json msgid "small closed loop extractor" msgid_plural "small closed loop extractors" -msgstr[0] "" +msgstr[0] "小型闭环萃取器" #. ~ Use action msg for {'str': 'small closed loop extractor'}. #: data/json/obsoletion/items.json @@ -145599,7 +145852,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "small closed loop extractor (on)" msgid_plural "small closed loop extractors (on)" -msgstr[0] "" +msgstr[0] "小型闭环萃取器(开)" #. ~ Use action msg for {'str': 'small closed loop extractor (on)', 'str_pl': #. 'small closed loop extractors (on)'}. @@ -145618,7 +145871,7 @@ msgstr "这台小型闭环萃取器正在运行中,只需要在它的金属管 #: data/json/obsoletion/items.json msgid "large closed loop extractor" msgid_plural "large closed loop extractors" -msgstr[0] "" +msgstr[0] "大型闭环萃取器" #. ~ Use action msg for {'str': 'large closed loop extractor'}. #: data/json/obsoletion/items.json @@ -145646,7 +145899,7 @@ msgstr "" #: data/json/obsoletion/items.json msgid "large closed loop extractor (on)" msgid_plural "large closed loop extractors (on)" -msgstr[0] "" +msgstr[0] "大型闭环萃取器(开)" #. ~ Use action msg for {'str': 'large closed loop extractor (on)', 'str_pl': #. 'large closed loop extractors (on)'}. @@ -145665,7 +145918,7 @@ msgstr "这台大型闭环萃取器正在运行中,只需要在它的金属管 #: data/json/obsoletion/items.json msgid "makeshift essential oil extractor" msgid_plural "makeshift essential oil extractors" -msgstr[0] "" +msgstr[0] "自制精油萃取器" #. ~ Description for {'str': 'makeshift essential oil extractor'} #: data/json/obsoletion/items.json @@ -145678,7 +145931,7 @@ msgstr "一台自制精油萃取器。基本上就是个55加仑大桶,配上 #: data/json/obsoletion/items.json msgid "qualitative filter paper" msgid_plural "qualitative filter paper" -msgstr[0] "" +msgstr[0] "定性滤纸" #. ~ Description for {'str_sp': 'qualitative filter paper'} #: data/json/obsoletion/items.json @@ -145691,7 +145944,7 @@ msgstr "能将固体从液体中分离出来的滤纸。这种滤纸的过滤等 #: data/json/obsoletion/items.json msgid "quantitative filter paper" msgid_plural "quantitative filter paper" -msgstr[0] "" +msgstr[0] "定量滤纸" #. ~ Description for {'str_sp': 'quantitative filter paper'} #: data/json/obsoletion/items.json @@ -145704,7 +145957,7 @@ msgstr "能将固体从液体中分离出来的滤纸。这种滤纸的过滤等 #: data/json/obsoletion/items.json msgid "recovery pump" msgid_plural "recovery pumps" -msgstr[0] "" +msgstr[0] "回收泵" #. ~ Description for {'str': 'recovery pump'} #: data/json/obsoletion/items.json @@ -147629,7 +147882,7 @@ msgstr "葡萄園" #: data/json/overmap/overmap_terrain/overmap_terrain_agricultural.json msgid "stills" -msgstr "蒸餾器" +msgstr "酿酒厂" #: data/json/overmap/overmap_terrain/overmap_terrain_agricultural.json #: data/mods/alt_map_key/overmap_terrain.json @@ -166649,7 +166902,7 @@ msgstr "機器人調度中心" #: data/mods/Aftershock/items/ammo_type.json msgid "acidic bore" msgid_plural "acidic bores" -msgstr[0] "" +msgstr[0] "酸液炮弹" #. ~ Description for {'str': 'acidic bore'} #: data/mods/Aftershock/items/ammo.json @@ -166661,7 +166914,7 @@ msgstr "这个正在蠕动的结节完全由树脂和血肉融合而成,似乎 #: data/mods/Aftershock/items/ammo.json msgid "x-ray laser barrel" msgid_plural "x-ray laser barrels" -msgstr[0] "" +msgstr[0] "X射线激光充能枪管" #. ~ Description for {'str': 'x-ray laser barrel'} #: data/mods/Aftershock/items/ammo.json @@ -166676,7 +166929,7 @@ msgstr "充能枪管" #: data/mods/Aftershock/items/armor.json msgid "bag of holding" msgid_plural "bags of holding" -msgstr[0] "" +msgstr[0] "次元袋" #. ~ Description for {'str': 'bag of holding', 'str_pl': 'bags of holding'} #: data/mods/Aftershock/items/armor.json @@ -166705,7 +166958,7 @@ msgstr "這款輕質盔甲背心由鈦合金縫製而成,布料襯墊舒適。 #: data/mods/Aftershock/items/armor.json msgid "hologram cloak mk.2" msgid_plural "hologram cloak mk.2s" -msgstr[0] "" +msgstr[0] "全息投影披风MK.II型" #. ~ Description for {'str': 'hologram cloak mk.2'} #: data/mods/Aftershock/items/armor.json @@ -166720,7 +166973,7 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "sentinel-lx cloak" msgid_plural "sentinel-lx cloaks" -msgstr[0] "" +msgstr[0] "哨兵-LX披风" #. ~ Description for {'str': 'sentinel-lx cloak'} #: data/mods/Aftershock/items/armor.json @@ -166733,7 +166986,7 @@ msgstr "哨兵-lx型机器人的超黑色长披风,披在肩上如同一个实 #: data/mods/Aftershock/items/armor.json msgid "XL jeans" msgid_plural "pairs of XL jeans" -msgstr[0] "" +msgstr[0] "牛仔裤(XL)" #. ~ Description for {'str': 'XL jeans', 'str_pl': 'pairs of XL jeans'} #: data/mods/Aftershock/items/armor.json @@ -166745,7 +166998,7 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "XL work pants" msgid_plural "pairs of XL work pants" -msgstr[0] "" +msgstr[0] "工装裤(XL)" #: data/mods/Aftershock/items/armor.json msgid "A pair of XL blue work pants." @@ -166762,7 +167015,7 @@ msgstr "一条特大号的浅蓝色裤子,工作时穿穿还是不错的。" #: data/mods/Aftershock/items/armor.json msgid "XL work t-shirt" msgid_plural "XL work t-shirts" -msgstr[0] "" +msgstr[0] "工作T恤(XL)" #. ~ Description for {'str': 'XL work t-shirt'} #: data/mods/Aftershock/items/armor.json @@ -166784,7 +167037,7 @@ msgstr "一件特大号的浅蓝色T恤,前面还有个小口袋。" #: data/mods/Aftershock/items/armor.json msgid "Uplifted SWAT armor" msgid_plural "Uplifted SWAT armors" -msgstr[0] "" +msgstr[0] "基因擢升部队SWAT装甲" #. ~ Description for {'str': 'Uplifted SWAT armor'} #: data/mods/Aftershock/items/armor.json @@ -166797,7 +167050,7 @@ msgstr "一件特大号的黑色战术防弹护甲,带有许多战术口袋, #: data/mods/Aftershock/items/armor.json msgid "empty XL ballistic vest" msgid_plural "empty XL ballistic vests" -msgstr[0] "" +msgstr[0] "防弹背心(空)(XL)" #. ~ Description for {'str': 'empty XL ballistic vest'} #: data/mods/Aftershock/items/armor.json @@ -166809,7 +167062,7 @@ msgstr "没有插入装甲板的加大号防弹背心。软质装甲板带依旧 #: data/mods/Aftershock/items/armor.json msgid "XL ESAPI ballistic vest" msgid_plural "XL ESAPI ballistic vests" -msgstr[0] "" +msgstr[0] "防弹背心(ESAPI)(XL)" #. ~ Description for {'str': 'XL ESAPI ballistic vest'} #: data/mods/Aftershock/items/armor.json @@ -166819,7 +167072,7 @@ msgstr "带有ESAPI陶瓷装甲板的加大号防弹衣。" #: data/mods/Aftershock/items/armor.json msgid "pair of XL combat boots" msgid_plural "pair of XL combat boots" -msgstr[0] "" +msgstr[0] "战斗靴(XL)" #. ~ Description for {'str_sp': 'pair of XL combat boots'} #: data/mods/Aftershock/items/armor.json @@ -166831,7 +167084,7 @@ msgstr "" #: data/mods/Aftershock/items/armor.json msgid "pair of XL tactical gloves" msgid_plural "pair of XL tactical gloves" -msgstr[0] "" +msgstr[0] "战术手套(XL)" #. ~ Description for {'str_sp': 'pair of XL tactical gloves'} #: data/mods/Aftershock/items/armor.json @@ -166843,7 +167096,7 @@ msgstr "一双加大号的凯夫拉强化战术手套,有防震,防滑等功 #: data/mods/Aftershock/items/armor.json msgid "pair of Killophant gloves" msgid_plural "pair of Killophant gloves" -msgstr[0] "" +msgstr[0] "“杀人象”部队战术手套" #. ~ Description for {'str_sp': 'pair of Killophant gloves'} #: data/mods/Aftershock/items/armor.json @@ -166856,7 +167109,7 @@ msgstr "一双凯夫拉强化战术手套,有防震、防滑等功能,是为 #: data/mods/Aftershock/items/armor.json msgid "XL leather belt" msgid_plural "XL leather belts" -msgstr[0] "" +msgstr[0] "皮带(XL)" #. ~ Description for {'str': 'XL leather belt'} #: data/mods/Aftershock/items/armor.json @@ -166868,7 +167121,7 @@ msgstr "一条特大号的皮革腰带。能让裤子穿起来更合身。" #: data/mods/Aftershock/items/armor.json msgid "XL police duty belt" msgid_plural "XL police duty belts" -msgstr[0] "" +msgstr[0] "警用执勤腰带(XL)" #. ~ Description for {'str': 'XL police duty belt'} #: data/mods/Aftershock/items/armor.json @@ -166880,7 +167133,7 @@ msgstr "一条特大号的黑色皮带,适合那些体型巨大的基因擢升 #: data/mods/Aftershock/items/armor.json msgid "XL tactical full helmet" msgid_plural "XL tactical full helmets" -msgstr[0] "" +msgstr[0] "战术全覆头盔(XL)" #. ~ Description for {'str': 'XL tactical full helmet'} #: data/mods/Aftershock/items/armor.json @@ -166892,7 +167145,7 @@ msgstr "一顶特大号的黑色极简头盔,覆盖面部和颈部,保护你 #: data/mods/Aftershock/items/armor.json msgid "XL leg ammo pouch" msgid_plural "XL leg ammo pouches" -msgstr[0] "" +msgstr[0] "弹匣包(腿)(XL)" #. ~ Description for {'str': 'XL leg ammo pouch', 'str_pl': 'XL leg ammo #. pouches'} @@ -166905,7 +167158,7 @@ msgstr "一个绑在腿上的大布包,能够装下两个弹匣,保证弹药 #: data/mods/Aftershock/items/armor.json msgid "HERC rig" msgid_plural "HERC rigs" -msgstr[0] "" +msgstr[0] "HERC装置" #. ~ Description for {'str': 'HERC rig'} #: data/mods/Aftershock/items/armor.json @@ -166920,7 +167173,7 @@ msgstr "" #: data/mods/Aftershock/items/bioparts.json msgid "living brain in a jar" msgid_plural "jars full of living brains" -msgstr[0] "" +msgstr[0] "缸中之脑" #. ~ Description for {'str': 'living brain in a jar', 'str_pl': 'jars full of #. living brains'} @@ -166933,7 +167186,7 @@ msgstr "这个罐子里装着一个人类的大脑,并由米·戈科技维持 #: data/mods/Aftershock/items/bioparts.json msgid "humming heart" msgid_plural "humming hearts" -msgstr[0] "" +msgstr[0] "蜂鸣之心" #. ~ Description for {'str': 'humming heart'} #: data/mods/Aftershock/items/bioparts.json @@ -166947,7 +167200,7 @@ msgstr "" #: data/mods/Aftershock/items/bioparts.json msgid "sensory cluster" msgid_plural "sensory clusters" -msgstr[0] "" +msgstr[0] "感官集簇" #. ~ Description for {'str': 'sensory cluster'} #: data/mods/Aftershock/items/bioparts.json @@ -166963,7 +167216,7 @@ msgstr "" #: data/mods/Aftershock/items/bioparts.json msgid "bioweapon chassis" msgid_plural "bioweapon chassis" -msgstr[0] "" +msgstr[0] "生物武器底盘" #. ~ Description for {'str_sp': 'bioweapon chassis'} #: data/mods/Aftershock/items/bioparts.json @@ -166977,7 +167230,7 @@ msgstr "" #: data/mods/Aftershock/items/bioparts.json msgid "broken mi-go turret" msgid_plural "broken mi-go turrets" -msgstr[0] "" +msgstr[0] "米·戈炮塔(损坏)" #. ~ Description for {'str': 'broken mi-go turret'} #: data/mods/Aftershock/items/bioparts.json @@ -166989,7 +167242,7 @@ msgstr "一个损坏的米·戈炮塔。它正在泄漏出你无法辨认的气 #: data/mods/Aftershock/items/bioparts.json msgid "vibrating bioblaster" msgid_plural "vibrating bioblasters" -msgstr[0] "" +msgstr[0] "生化热熔炮(颤动)" #: data/mods/Aftershock/items/bioparts.json msgid "" @@ -167082,7 +167335,7 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Nuclear Physics Made Easy" msgid_plural "copies of Nuclear Physics Made Easy" -msgstr[0] "" +msgstr[0] "核物理轻松入门教程" #. ~ Description for {'str': 'Nuclear Physics Made Easy', 'str_pl': 'copies of #. Nuclear Physics Made Easy'} @@ -167095,7 +167348,7 @@ msgstr "一本教科书,详细介绍了最尖端的核能技术的运作流程 #: data/mods/Aftershock/items/books.json msgid "Cyrus Whateley's Notes on Repurposing mi-go victims" msgid_plural "copies of Cyrus Whateley's Notes" -msgstr[0] "" +msgstr[0] "赛勒斯·沃特利的笔记" #. ~ Description for {'str': "Cyrus Whateley's Notes on Repurposing mi-go #. victims", 'str_pl': "copies of Cyrus Whateley's Notes"} @@ -167108,7 +167361,7 @@ msgstr "疯子写的一页账单。他们似乎在提供一些使死者复活的 #: data/mods/Aftershock/items/books.json msgid "Dr Moreau and You" msgid_plural "copies of Dr Moreau and You" -msgstr[0] "" +msgstr[0] "莫洛博士与你" #. ~ Description for {'str': 'Dr Moreau and You', 'str_pl': 'copies of Dr #. Moreau and You'} @@ -167124,7 +167377,7 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Millyficent's Diary" msgid_plural "copies of Millyficent's Diary" -msgstr[0] "" +msgstr[0] "米利菲森的日记" #. ~ Description for {'str': "Millyficent's Diary", 'str_pl': "copies of #. Millyficent's Diary"} @@ -167140,7 +167393,7 @@ msgstr "" #: data/mods/Aftershock/items/books.json msgid "Unusual Ammunitions of the Corporations" msgid_plural "copies of Unusual Ammunitions of the Corporations" -msgstr[0] "" +msgstr[0] "巨型企业罕见弹药目录" #. ~ Description for {'str': 'Unusual Ammunitions of the Corporations', #. 'str_pl': 'copies of Unusual Ammunitions of the Corporations'} @@ -167155,7 +167408,7 @@ msgstr "" #: data/mods/Aftershock/items/cast_spell_items.json msgid "caster" msgid_plural "casters" -msgstr[0] "" +msgstr[0] "施法器" #. ~ Description for {'str': 'caster'} #: data/mods/Aftershock/items/cast_spell_items.json @@ -167165,7 +167418,7 @@ msgstr "一个用于施法的虚拟科技法师的小玩意。" #: data/mods/Aftershock/items/cast_spell_items.json msgid "hologram transposition caster" msgid_plural "hologram transposition casters" -msgstr[0] "" +msgstr[0] "全息换位施法器" #. ~ Description for {'str': 'hologram transposition caster'} #: data/mods/Aftershock/items/cast_spell_items.json @@ -167177,7 +167430,7 @@ msgstr "一个小型金属球体,顶部有个凹进的底座。激活后,它 #: data/mods/Aftershock/items/cast_spell_items.json msgid "hologram flare caster" msgid_plural "hologram flare casters" -msgstr[0] "" +msgstr[0] "全息闪光施法器" #. ~ Description for {'str': 'hologram flare caster'} #: data/mods/Aftershock/items/cast_spell_items.json @@ -167190,7 +167443,7 @@ msgstr "一个小型金属球体,顶部有个凹进的底座。激活后,选 #: data/mods/Aftershock/items/cast_spell_items.json msgid "decoy caster" msgid_plural "decoy casters" -msgstr[0] "" +msgstr[0] "全息诱饵施法器" #. ~ Description for {'str': 'decoy caster'} #: data/mods/Aftershock/items/cast_spell_items.json @@ -167202,7 +167455,7 @@ msgstr "一个小型金属球体,顶部有个凹进的底座。激活后,它 #: data/mods/Aftershock/items/cast_spell_items.json msgid "decoy field caster" msgid_plural "decoy field casters" -msgstr[0] "" +msgstr[0] "全息力场施法器" #. ~ Description for {'str': 'decoy field caster'} #: data/mods/Aftershock/items/cast_spell_items.json @@ -167214,7 +167467,7 @@ msgstr "一个小型金属球体,顶部有个凹进的底座。激活后,它 #: data/mods/Aftershock/items/cbms.json msgid "Wind Turbine CBM" msgid_plural "Wind Turbine CBMs" -msgstr[0] "" +msgstr[0] "风力发电机CBM" #. ~ Description for {'str': 'Wind Turbine CBM'} #. ~ Description for {'str': 'Wind Turbines'} @@ -167230,7 +167483,7 @@ msgstr "你的身上安装了一排可伸缩的风力发电机。开启后,它 #: data/mods/Aftershock/player/bionics.json msgid "Cranium Bomb" msgid_plural "Cranium Bombs" -msgstr[0] "" +msgstr[0] "颅骨炸弹" #. ~ Description for {'str': 'Cranium Bomb'} #: data/mods/Aftershock/items/cbms.json @@ -167243,7 +167496,7 @@ msgstr "一个安装在脊柱和脑干交汇处的炸弹。它在安装时就被 #: data/mods/Aftershock/player/bionics.json msgid "Skullgun CBM" msgid_plural "Skullgun CBMs" -msgstr[0] "" +msgstr[0] "头骨枪CBM" #. ~ Description for {'str': 'Skullgun CBM'} #: data/mods/Aftershock/items/cbms.json @@ -167257,7 +167510,7 @@ msgstr "你的头骨中隐藏着一只 .40 口径单发手枪。激活这个生 #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "nutriment" msgid_plural "nutriments" -msgstr[0] "" +msgstr[0] "营养素片" #. ~ Description for nutriment #: data/mods/Aftershock/items/comestibles.json @@ -167272,7 +167525,7 @@ msgstr "一種白色藥丸,半個拇指大小,含有維生素和熱量。提 #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "nutriment water" msgid_plural "nutriment waters" -msgstr[0] "" +msgstr[0] "营养素液" #. ~ Description for nutriment water #: data/mods/Aftershock/items/comestibles.json @@ -167285,7 +167538,7 @@ msgstr "溶解在水中以稀釋其味道的營養丸。令人不安的酷似變 #: data/mods/Aftershock/items/comestibles.json msgid "sundew" msgid_plural "sundews" -msgstr[0] "" +msgstr[0] "阳光水" #. ~ Description for sundew #: data/mods/Aftershock/items/comestibles.json @@ -167299,7 +167552,7 @@ msgstr "用某種化合物處理過的水。它無法凍結,非常輕,並且 #: data/mods/Aftershock/items/comestibles/comestibles.json msgid "sungel" msgid_plural "sungels" -msgstr[0] "" +msgstr[0] "阳光凝胶" #. ~ Use action activation_message for sungel. #: data/mods/Aftershock/items/comestibles.json @@ -167321,7 +167574,7 @@ msgstr "與嗎啡混合後,這種太陽露凝固了,並具有巨大的刺激 #: data/mods/Aftershock/items/obsolete.json msgid "sunesthesia" msgid_plural "sunesthesias" -msgstr[0] "" +msgstr[0] "阳光麻醉剂" #. ~ Use action activation_message for sunesthesia. #: data/mods/Aftershock/items/comestibles.json @@ -167342,7 +167595,7 @@ msgstr "混合了多种毒品的阳光凝胶,但却没有任何副作用。其 #: data/mods/Aftershock/items/corpses.json msgid "broken sentinel-lx" msgid_plural "broken sentinels-lx" -msgstr[0] "" +msgstr[0] "哨兵-LX型机器人(损坏)" #. ~ Description for {'str': 'broken sentinel-lx', 'str_pl': 'broken #. sentinels-lx'} @@ -167355,7 +167608,7 @@ msgstr "一个损坏的哨兵-LX型机器人。可以拆解得到部件。" #: data/mods/Aftershock/items/corpses.json msgid "broken bloodhound drone" msgid_plural "broken bloodhound drones" -msgstr[0] "" +msgstr[0] "猎犬无人机(损坏)" #. ~ Description for {'str': 'broken bloodhound drone'} #: data/mods/Aftershock/items/corpses.json @@ -167380,17 +167633,17 @@ msgstr "一隻損毀的輔助機器人,它現在很安靜、死氣沉沉。可 #: data/mods/Aftershock/items/corpses.json msgid "broken beehive robot" msgid_plural "broken beehive robots" -msgstr[0] "" +msgstr[0] "蜂巢机器人(损坏)" #: data/mods/Aftershock/items/corpses.json msgid "broken xray laser turret" msgid_plural "broken xray laser turrets" -msgstr[0] "" +msgstr[0] "激光炮塔(损坏)" #: data/mods/Aftershock/items/corpses.json msgid "broken Whately turret" msgid_plural "broken Whately turrets" -msgstr[0] "" +msgstr[0] "沃特利脑熔炮塔(损坏)" #: data/mods/Aftershock/items/corpses.json msgid "broken butler-bot" @@ -167609,7 +167862,7 @@ msgstr "這是一台損毀的醫療機器人,現在它一動也不動,可以 #: data/mods/Aftershock/items/frankenstein_items.json msgid "inactive frankenstein" msgid_plural "inactive frankensteins" -msgstr[0] "" +msgstr[0] "科学怪人(关)" #. ~ Description for inactive frankenstein #: data/mods/Aftershock/items/frankenstein_items.json @@ -167633,7 +167886,7 @@ msgstr "" #: data/mods/Aftershock/items/grenades.json msgid "electroshock grenade" msgid_plural "electroshock grenades" -msgstr[0] "" +msgstr[0] "电击手雷" #. ~ Description for electroshock grenade #: data/mods/Aftershock/items/grenades.json @@ -167646,7 +167899,7 @@ msgstr "电击手雷,使用此物品以拔掉保险销。之后五回合它就 #: data/mods/Aftershock/items/grenades.json msgid "armed electroshock grenade" msgid_plural "armed electroshock grenades" -msgstr[0] "" +msgstr[0] "电击手雷(激活)" #. ~ Description for armed electroshock grenade #: data/mods/Aftershock/items/grenades.json @@ -167657,7 +167910,7 @@ msgstr "这个电击手雷正在释放致命的电场。" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive brain blaster" msgid_plural "inactive brain blasters" -msgstr[0] "" +msgstr[0] "脑熔炮塔(关)" #. ~ Use action friendly_msg for {'str': 'inactive brain blaster'}. #: data/mods/Aftershock/items/inactiverobot.json @@ -167718,7 +167971,7 @@ msgstr "三足机器人锁定了你,点燃的喷火器直接瞄准了你。看 #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive sentinel-lx" msgid_plural "inactive sentinel-lxs" -msgstr[0] "" +msgstr[0] "哨兵-LX型机器人(关)" #. ~ Description for {'str': 'inactive sentinel-lx'} #: data/mods/Aftershock/items/inactiverobot.json @@ -167734,7 +167987,7 @@ msgstr "" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive bloodhound drone" msgid_plural "inactive bloodhound drones" -msgstr[0] "" +msgstr[0] "猎犬无人机(关)" #. ~ Use action friendly_msg for {'str': 'inactive bloodhound drone'}. #: data/mods/Aftershock/items/inactiverobot.json @@ -167788,7 +168041,7 @@ msgstr[0] "未啟動的醫療機器人" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive utilibot" msgid_plural "inactive utilibots" -msgstr[0] "" +msgstr[0] "通用机器人(关)" #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive hack" @@ -167836,7 +168089,7 @@ msgstr "一台动力耗尽的军用机器人,装上了一把内置7.62x51mm口 #: data/mods/Aftershock/items/inactiverobot.json msgid "inactive floating heater" msgid_plural "inactive floating heaters" -msgstr[0] "" +msgstr[0] "浮空加热器(关)" #. ~ Description for inactive floating heater #: data/mods/Aftershock/items/inactiverobot.json @@ -167891,7 +168144,7 @@ msgstr "一台改装的掠行机器人,装上了一把内置8mm无壳弹枪械 #: data/mods/Aftershock/items/items.json msgid "Crypto coin" msgid_plural "Crypto coins" -msgstr[0] "" +msgstr[0] "加密币" #. ~ Description for {'str': 'Crypto coin'} #: data/mods/Aftershock/items/items.json @@ -167906,7 +168159,7 @@ msgstr "" msgctxt "container" msgid "basin" msgid_plural "basins" -msgstr[0] "" +msgstr[0] "简易钢盆" #. ~ Description for {'ctxt': 'container', 'str': 'basin'} #: data/mods/Aftershock/items/items.json @@ -168011,7 +168264,7 @@ msgstr "平底鍋,鐵鍋,加熱板和化學儀器套組。製作食物和化 #: data/mods/Aftershock/items/items.json msgid "nuclear waste" msgid_plural "nuclear waste" -msgstr[0] "" +msgstr[0] "核废料" #. ~ Description for {'str_sp': 'nuclear waste'} #: data/mods/Aftershock/items/items.json @@ -168041,7 +168294,7 @@ msgstr "一個代表用作存放危險物質的黃色圓桶。" #: data/mods/Aftershock/items/items.json msgid "folded atomic butter churn" msgid_plural "folded atomic butter churns" -msgstr[0] "" +msgstr[0] "原子黄油搅拌机(折叠)" #. ~ Description for {'str': 'folded atomic butter churn'} #: data/mods/Aftershock/items/items.json @@ -168057,12 +168310,12 @@ msgstr "" #: data/mods/Aftershock/items/items.json msgid "deployed atomic butter churn" msgid_plural "deployed atomic butter churns" -msgstr[0] "" +msgstr[0] "已部署的原子黄油搅拌机" #: data/mods/Aftershock/items/items.json msgid "titanium" msgid_plural "titanium" -msgstr[0] "" +msgstr[0] "钛" #. ~ Description for {'str_sp': 'titanium'} #: data/mods/Aftershock/items/items.json @@ -168077,7 +168330,7 @@ msgstr "" #: data/mods/Aftershock/items/items.json msgid "titanium implant" msgid_plural "titanium implants" -msgstr[0] "" +msgstr[0] "钛制植体" #. ~ Description for {'str': 'titanium implant'} #: data/mods/Aftershock/items/items.json @@ -168089,7 +168342,7 @@ msgstr "一款植入人体体内的医用植入物,用于矫正如臀部或背 #: data/mods/Aftershock/items/items.json msgid "titanium tooth" msgid_plural "titanium tooths" -msgstr[0] "" +msgstr[0] "钛制假牙" #. ~ Description for {'str': 'titanium tooth'} #: data/mods/Aftershock/items/items.json @@ -168101,7 +168354,7 @@ msgstr "一款由纯钛制成的牙科植入物,由于其良好的生物相容 #: data/mods/Aftershock/items/items.json msgid "titanium watch" msgid_plural "titanium watches" -msgstr[0] "" +msgstr[0] "钛制手表" #. ~ Description for {'str': 'titanium watch', 'str_pl': 'titanium watches'} #: data/mods/Aftershock/items/items.json @@ -168113,7 +168366,7 @@ msgstr "一块厚实的男性手表,由钛制成。它十分耐用,轻便且 #: data/mods/Aftershock/items/items.json msgid "titanium ring" msgid_plural "titanium rings" -msgstr[0] "" +msgstr[0] "钛戒指" #. ~ Description for {'str': 'titanium ring'} #: data/mods/Aftershock/items/items.json @@ -168133,7 +168386,7 @@ msgstr "石墨烯编织" #: data/mods/Aftershock/items/mutagen.json msgid "mi-go serum" msgid_plural "mi-go serums" -msgstr[0] "" +msgstr[0] "米·戈血清" #. ~ Description for mi-go serum #: data/mods/Aftershock/items/mutagen.json @@ -168145,7 +168398,7 @@ msgstr "超浓缩的诱变剂,看上去就像熔岩灯一样。你需要一个 #: data/mods/Aftershock/items/mutagen.json msgid "mi-go mutagen" msgid_plural "mi-go mutagens" -msgstr[0] "" +msgstr[0] "米·戈诱变剂" #. ~ Description for mi-go mutagen #: data/mods/Aftershock/items/mutagen.json @@ -168156,7 +168409,7 @@ msgstr "一种极度罕见的混合诱变剂,闻上去就像是硫磺,散发 #: data/mods/Aftershock/items/mutagen.json msgid "mastodon serum" msgid_plural "mastodon serums" -msgstr[0] "" +msgstr[0] "乳齿象血清" #. ~ Description for {'str': 'mastodon serum'} #. ~ Description for {'str': 'stego serum'} @@ -168170,7 +168423,7 @@ msgstr "超浓缩的诱变剂,不适合那些恐惧此类事物的人。你需 #: data/mods/Aftershock/items/mutagen.json msgid "mastodon mutagen" msgid_plural "mastodon mutagens" -msgstr[0] "" +msgstr[0] "乳齿象诱变剂" #. ~ Description for {'str': 'mastodon mutagen'} #. ~ Description for {'str': 'stego mutagen'} @@ -168195,7 +168448,7 @@ msgstr "卡車拖車用來運輸大量物品的巨大儲放空間。" #: data/mods/Aftershock/items/obsolete.json msgid "precision solderers" msgid_plural "precision solderers" -msgstr[0] "" +msgstr[0] "精密焊接仪" #: data/mods/Aftershock/items/obsolete.json msgid "Precision Solderers CBM" @@ -168219,7 +168472,7 @@ msgstr "一个巨大的金属空间,与载具车顶的延伸部分结合在一 #: data/mods/Aftershock/items/obsolete.json msgid "dough" msgid_plural "doughs" -msgstr[0] "" +msgstr[0] "面团" #. ~ Description for dough #: data/mods/Aftershock/items/obsolete.json @@ -168247,7 +168500,7 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "hazardous environment helmet" msgid_plural "hazardous environment helmets" -msgstr[0] "" +msgstr[0] "危险环境防护头盔" #. ~ Use action msg for hazardous environment helmet. #: data/mods/Aftershock/items/obsolete.json @@ -168267,7 +168520,7 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "hazardous environment helmet (on)" msgid_plural "hazardous environment helmets (on)" -msgstr[0] "" +msgstr[0] "危险环境防护头盔(开)" #. ~ Description for {'str': 'hazardous environment helmet (on)', 'str_pl': #. 'hazardous environment helmets (on)'} @@ -168319,7 +168572,7 @@ msgstr "一件巨大的拼布羊毛被子。非常,非常溫暖。" #: data/mods/Aftershock/items/obsolete.json msgid "survivor utility belt (holster)" msgid_plural "survivor utility belts (holster)" -msgstr[0] "" +msgstr[0] "幸存者工具带(枪套)" #. ~ Description for {'str': 'survivor utility belt (holster)', 'str_pl': #. 'survivor utility belts (holster)'} @@ -168335,7 +168588,7 @@ msgstr "" #: data/mods/Aftershock/items/obsolete.json msgid "survivor utility belt (sheath)" msgid_plural "survivor utility belts (sheath)" -msgstr[0] "" +msgstr[0] "幸存者工具带(刀鞘)" #: data/mods/Aftershock/items/obsolete.json msgid "brigandine" @@ -168380,7 +168633,7 @@ msgstr "一件仿照中世纪的镶片皮甲制成的自制\"防弹衣\",它 #: data/mods/Aftershock/items/obsolete.json msgid "makeshift rail rifle" msgid_plural "makeshift rail rifles" -msgstr[0] "" +msgstr[0] "自制轨道步枪" #: data/mods/Aftershock/items/obsolete.json msgid "" @@ -168394,7 +168647,7 @@ msgstr "" #: data/mods/Aftershock/items/seed.json msgid "pineapple stem" msgid_plural "pineapple stem" -msgstr[0] "" +msgstr[0] "菠萝根茎" #. ~ Description for {'str_sp': 'pineapple stem'} #: data/mods/Aftershock/items/seed.json @@ -168404,7 +168657,7 @@ msgstr "菠萝的根茎,你可以用它来种出你自己的菠萝。" #: data/mods/Aftershock/items/seed.json msgid "melon seeds" msgid_plural "melon seeds" -msgstr[0] "" +msgstr[0] "甜瓜种子" #. ~ Description for {'str_sp': 'melon seeds'} #: data/mods/Aftershock/items/seed.json @@ -168414,7 +168667,7 @@ msgstr "一些甜瓜种子。" #: data/mods/Aftershock/items/seed.json msgid "banana saplings" msgid_plural "banana saplings" -msgstr[0] "" +msgstr[0] "香蕉种苗" #. ~ Description for {'str_sp': 'banana saplings'} #: data/mods/Aftershock/items/seed.json @@ -168424,7 +168677,7 @@ msgstr "一些香蕉种苗。" #: data/mods/Aftershock/items/seed.json msgid "orange vine" msgid_plural "orange vine" -msgstr[0] "" +msgstr[0] "橙子种苗" #. ~ Description for {'str_sp': 'orange vine'} #: data/mods/Aftershock/items/seed.json @@ -168434,7 +168687,7 @@ msgstr "一些橘子种苗。肯定是转基因产品。" #: data/mods/Aftershock/items/seed.json msgid "lemon vine" msgid_plural "lemon vine" -msgstr[0] "" +msgstr[0] "柠檬种苗" #. ~ Description for {'str_sp': 'lemon vine'} #: data/mods/Aftershock/items/seed.json @@ -168444,7 +168697,7 @@ msgstr "一些柠檬种苗。肯定是转基因产品。" #: data/mods/Aftershock/items/seed.json msgid "subterraenean coconut" msgid_plural "subterraenean coconut" -msgstr[0] "" +msgstr[0] "地下椰子" #. ~ Description for {'str_sp': 'subterraenean coconut'} #: data/mods/Aftershock/items/seed.json @@ -168454,7 +168707,7 @@ msgstr "证明人类在大灾变之前走得太远了。" #: data/mods/Aftershock/items/tool_armor.json msgid "cryopod bodyglove" msgid_plural "cryopod bodygloves" -msgstr[0] "" +msgstr[0] "冬眠舱连身衣" #. ~ Description for {'str': 'cryopod bodyglove'} #: data/mods/Aftershock/items/tool_armor.json @@ -168469,7 +168722,7 @@ msgstr "" #: data/mods/Aftershock/items/tool_armor.json msgid "cryopod bodyglove (on)" msgid_plural "cryopod bodygloves (on)" -msgstr[0] "" +msgstr[0] "冬眠舱连身衣(开)" #. ~ Description for {'str': 'cryopod bodyglove (on)', 'str_pl': 'cryopod #. bodygloves (on)'} @@ -168502,7 +168755,7 @@ msgstr "" #: data/mods/Aftershock/items/tools.json msgid "atomic smartphone - music" msgid_plural "atomic smartphones - music" -msgstr[0] "" +msgstr[0] "原子智能手机(音乐)" #: data/mods/Aftershock/items/tools.json msgid "atomic smartphone - Flashlight" @@ -168512,7 +168765,7 @@ msgstr[0] "原子智慧型手機 - 手電筒模式" #: data/mods/Aftershock/items/tools.json msgid "Wraitheon executive's smartphone" msgid_plural "Wraitheon executive's smartphones" -msgstr[0] "" +msgstr[0] "\"幽灵怪\"公司高管智能手机" #. ~ Description for {'str': "Wraitheon executive's smartphone"} #: data/mods/Aftershock/items/tools.json @@ -168524,12 +168777,12 @@ msgstr "定制版原子智能手机。值得一提的是内部集成了一个保 #: data/mods/Aftershock/items/tools.json msgid "Wraitheon executive's smartphone - music" msgid_plural "Wraitheon executive's smartphones - music" -msgstr[0] "" +msgstr[0] "\"幽灵怪\"公司高管智能手机(音乐)" #: data/mods/Aftershock/items/tools.json msgid "Executive's smartphone - Flashlight" msgid_plural "Executive's smartphones - Flashlight" -msgstr[0] "" +msgstr[0] "高管智能手机(手电筒)" #: data/mods/Aftershock/items/tools.json msgid "atompot" @@ -168564,7 +168817,7 @@ msgstr "一种可调节的链式扳手,设计用于难以触及的地方。由 #: data/mods/Aftershock/items/tools.json msgid "power cutter (off)" msgid_plural "power cutters (off)" -msgstr[0] "" +msgstr[0] "动力切割机(关闭)" #. ~ Use action msg for {'str': 'power cutter (off)', 'str_pl': 'power cutters #. (off)'}. @@ -168583,7 +168836,7 @@ msgstr "一种巨大的气动锯,带有金刚石锯片。如果有汽油作为 #: data/mods/Aftershock/items/tools.json msgid "power cutter (on)" msgid_plural "power cutters (on)" -msgstr[0] "" +msgstr[0] "动力切割机(开启)" #. ~ Use action msg for {'str': 'power cutter (on)', 'str_pl': 'power cutters #. (on)'}. @@ -168604,7 +168857,7 @@ msgstr "一个巨大的,气动的钻石锯片,目前正在疯狂旋转。它 #: data/mods/Aftershock/items/tools.json msgid "murdersaw (off)" msgid_plural "murdersaws (off)" -msgstr[0] "" +msgstr[0] "杀人锯(关)" #. ~ Use action msg for {'str': 'murdersaw (off)', 'str_pl': 'murdersaws #. (off)'}. @@ -168623,7 +168876,7 @@ msgstr "这台曾经的切割机已经被精简,去掉了所有不必要的安 #: data/mods/Aftershock/items/tools.json msgid "murdersaw (on)" msgid_plural "murdersaws (on)" -msgstr[0] "" +msgstr[0] "杀人锯(开)" #. ~ Use action msg for {'str': 'murdersaw (on)', 'str_pl': 'murdersaws #. (on)'}. @@ -168641,7 +168894,7 @@ msgstr "这件可怕的武器现在正在用它自己的力量发出巨大的声 #: data/mods/Aftershock/items/tools.json msgid "rope lighter" msgid_plural "rope lighters" -msgstr[0] "" +msgstr[0] "绳索打火机" #. ~ Description for {'str': 'rope lighter'} #: data/mods/Aftershock/items/tools.json @@ -168679,7 +168932,7 @@ msgstr "" #: data/mods/Aftershock/items/tools.json msgid "bionic maintenance toolkit" msgid_plural "bionic maintenance toolkits" -msgstr[0] "" +msgstr[0] "生化插件维护工具箱" #. ~ Description for {'str': 'bionic maintenance toolkit'} #: data/mods/Aftershock/items/tools.json @@ -168694,7 +168947,7 @@ msgstr "" #: data/mods/Aftershock/items/tools.json msgid "complete bionic toolkit" msgid_plural "complete bionic toolkits" -msgstr[0] "" +msgstr[0] "生化插件完全工具箱" #. ~ Description for {'str': 'complete bionic toolkit'} #: data/mods/Aftershock/items/tools.json @@ -168708,7 +168961,7 @@ msgstr "一整套非常小的自动化工具和加密所用的数字密钥,通 #: data/mods/Aftershock/items/tools.json msgid "cybernetic power port mod" msgid_plural "cybernetic power port mods" -msgstr[0] "" +msgstr[0] "生化能量接口模组" #. ~ Description for cybernetic power port mod #: data/mods/Aftershock/items/tools.json @@ -168737,7 +168990,7 @@ msgstr "" #: data/mods/Aftershock/items/weapons.json msgid "energy saber" msgid_plural "energy sabers" -msgstr[0] "" +msgstr[0] "能量剑" #. ~ Use action msg for {'str': 'energy saber'}. #: data/mods/Aftershock/items/weapons.json @@ -168759,7 +169012,7 @@ msgstr "一根和你手一样大的黑色管子。激活可生成一道强光剑 #: data/mods/Aftershock/items/weapons.json msgid "energy saber (active)" msgid_plural "energy sabers (active)" -msgstr[0] "" +msgstr[0] "能量剑(开)" #. ~ Use action msg for {'str': 'energy saber (active)', 'str_pl': 'energy #. sabers (active)'}. @@ -168782,7 +169035,7 @@ msgstr "" #: data/mods/Aftershock/items/weapons.json msgid "hard-light longbow" msgid_plural "hard-light longbows" -msgstr[0] "" +msgstr[0] "硬光长弓" #: data/mods/Aftershock/items/weapons.json msgid "" @@ -168843,7 +169096,7 @@ msgstr "這是一把由常見的零件製作的廉價雷射步槍。火力不高 #: data/mods/Aftershock/items/weapons.json msgid "titanium bat" msgid_plural "titanium bats" -msgstr[0] "" +msgstr[0] "钛制棒球棍" #. ~ Description for {'str': 'titanium bat'} #: data/mods/Aftershock/items/weapons.json @@ -168855,7 +169108,7 @@ msgstr "一根由钛制成的豪华棒球棒,因其性能大大提高导致防 #: data/mods/Aftershock/items/weapons.json msgid "bodyguard knife" msgid_plural "bodyguard knives" -msgstr[0] "" +msgstr[0] "保镖刀" #. ~ Description for {'str': 'bodyguard knife', 'str_pl': 'bodyguard knives'} #: data/mods/Aftershock/items/weapons.json @@ -168867,7 +169120,7 @@ msgstr "一把能够躲过安检措施的刀,这把刀是任何末日晚宴上 #: data/mods/Aftershock/items/weapons.json msgid "handheld x-ray cannon" msgid_plural "handheld x-ray cannons" -msgstr[0] "" +msgstr[0] "手持X射线激光加农炮" #: data/mods/Aftershock/items/weapons.json msgid "" @@ -168880,7 +169133,7 @@ msgstr "" #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "sundew classic" msgid_plural "sundew classics" -msgstr[0] "" +msgstr[0] "日落经典" #. ~ Description for sundew classic #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168894,7 +169147,7 @@ msgstr "一罐金灿灿的松露,世界上首屈一指的软饮料。盯着罐 #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "H₂O™" msgid_plural "H₂O™" -msgstr[0] "" +msgstr[0] "H₂O™水" #. ~ Description for {'str_sp': 'H₂O™'} #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168907,7 +169160,7 @@ msgstr "当希斯尔工业公司成功地注册了水的化学式配方专利时 #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "food cubes" msgid_plural "food cubes" -msgstr[0] "" +msgstr[0] "食立方™" #. ~ Description for {'str_sp': 'food cubes'} #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168918,7 +169171,7 @@ msgstr "顺滑混合食品,整齐列成立方,提供终极享受。" #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "Foodplace's Food-to-go™" msgid_plural "Foodplace's Food-to-go™" -msgstr[0] "" +msgstr[0] "美食广场美食条™" #. ~ Description for {'str_sp': "Foodplace's Food-to-go™"} #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168930,7 +169183,7 @@ msgstr "美食广场™出品的便携美食条™是每一位当代美食小子 #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "loop 'fruit'" msgid_plural "loop 'fruits'" -msgstr[0] "" +msgstr[0] "圈圈果™" #. ~ Description for {'str': "loop 'fruit'", 'str_pl': "loop 'fruits'"} #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168940,7 +169193,7 @@ msgstr "一堆富含焦糖和黄色色素的能量圈,尝起来并不太像苹 #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "cee wafers" msgid_plural "cee wafers" -msgstr[0] "" +msgstr[0] "西威孚™海藻饼干" #. ~ Description for {'str_sp': 'cee wafers'} #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168952,7 +169205,7 @@ msgstr "一些外表灰绿色的光滑薄脆饼干。用完全可以食用的海 #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "beefsim" msgid_plural "beefsims" -msgstr[0] "" +msgstr[0] "毕夫兴™能量棒" #. ~ Description for beefsim #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168966,7 +169219,7 @@ msgstr "" #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "soup, flavor 27" msgid_plural "soup, flavor 27" -msgstr[0] "" +msgstr[0] "汤™风味27#" #. ~ Description for {'str_sp': 'soup, flavor 27'} #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168980,7 +169233,7 @@ msgstr "" #: data/mods/Aftershock/items/comestibles/cheap_food.json msgid "caffex" msgid_plural "caffex" -msgstr[0] "" +msgstr[0] "咖啡X™" #. ~ Description for {'str_sp': 'caffex'} #: data/mods/Aftershock/items/comestibles/cheap_food.json @@ -168991,7 +169244,7 @@ msgstr "一种冒着白色肥皂状泡沫的深色饮料,工厂预先酿制罐 #: data/mods/Aftershock/items/crafting_scrap/abstract_scrap.json msgid "ur-scrap" msgid_plural "ur-scraps" -msgstr[0] "" +msgstr[0] "基础废料" #. ~ Description for {'str': 'ur-scrap'} #: data/mods/Aftershock/items/crafting_scrap/abstract_scrap.json @@ -169001,7 +169254,7 @@ msgstr "一个小型高科技玩意。" #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json msgid "monomeric slurry" msgid_plural "monomeric slurry" -msgstr[0] "" +msgstr[0] "单体溶液" #. ~ Description for {'str_sp': 'monomeric slurry'} #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json @@ -169013,7 +169266,7 @@ msgstr "一堆有机聚合物基本组分的混合体。如果你知道整套制 #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json msgid "micellular growth medium" msgid_plural "micellular growth mediums" -msgstr[0] "" +msgstr[0] "微细胞培养介质" #. ~ Description for {'str': 'micellular growth medium'} #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json @@ -169025,7 +169278,7 @@ msgstr "一种为了避免不同生物材料在混合过程中相互拮抗而设 #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json msgid "artificial muscle fibers" msgid_plural "artificial muscle fibers" -msgstr[0] "" +msgstr[0] "人工肌肉纤维材料" #. ~ Description for {'str_sp': 'artificial muscle fibers'} #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json @@ -169037,7 +169290,7 @@ msgstr "一种在实验室培养或通过3D生物打印技术生产出的肌肉 #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json msgid "self healing polymers" msgid_plural "self healing polymers" -msgstr[0] "" +msgstr[0] "自我修复聚合物" #. ~ Description for {'str_sp': 'self healing polymers'} #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json @@ -169050,7 +169303,7 @@ msgstr "" #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json msgid "autologous totipotent tissue culture" msgid_plural "autologous totipotent tissue cultures" -msgstr[0] "" +msgstr[0] "自体干细胞组织培养基" #. ~ Description for {'str': 'autologous totipotent tissue culture'} #: data/mods/Aftershock/items/crafting_scrap/biomaterial_scrap.json @@ -169062,7 +169315,7 @@ msgstr "未受污染的纯细胞物质,按照正确的步骤处理后能够成 #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json msgid "scrap photonics" msgid_plural "scrap photonics" -msgstr[0] "" +msgstr[0] "光子电路废料" #. ~ Description for {'str_sp': 'scrap photonics'} #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json @@ -169072,7 +169325,7 @@ msgstr "蓝色和金色的小型电路元件,通过光传输信号。" #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json msgid "photonic circuitry" msgid_plural "photonic circuitries" -msgstr[0] "" +msgstr[0] "光子电路元件" #. ~ Description for {'str': 'photonic circuitry', 'str_pl': 'photonic #. circuitries'} @@ -169083,7 +169336,7 @@ msgstr "一块镶嵌在深蓝色基底上的金光闪闪的网格状电路。" #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json msgid "photonic computation core" msgid_plural "photonic computation cores" -msgstr[0] "" +msgstr[0] "光子计算核心" #. ~ Description for {'str': 'photonic computation core'} #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json @@ -169093,7 +169346,7 @@ msgstr "一大块形状如同发光结晶立方体的单片电路。" #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json msgid "hypergeometric photonics" msgid_plural "hypergeometric photonics" -msgstr[0] "" +msgstr[0] "光子超几何体" #. ~ Description for {'str_sp': 'hypergeometric photonics'} #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json @@ -169105,7 +169358,7 @@ msgstr "你手掌般大小的元件中有个完全独立的数字宇宙。附着 #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json msgid "acausal logic permutator" msgid_plural "acausal logic permutators" -msgstr[0] "" +msgstr[0] "非因果逻辑变换器" #. ~ Description for {'str': 'acausal logic permutator'} #: data/mods/Aftershock/items/crafting_scrap/circuity_scrap.json @@ -169115,7 +169368,7 @@ msgstr "它已经给出了答案,而你还没有问任何问题。" #: data/mods/Aftershock/items/crafting_scrap/cloth_scrap.json msgid "woven metamaterial sheet" msgid_plural "woven metamaterial sheets" -msgstr[0] "" +msgstr[0] "超级材料织物" #. ~ Description for {'str': 'woven metamaterial sheet'} #: data/mods/Aftershock/items/crafting_scrap/cloth_scrap.json @@ -169126,7 +169379,7 @@ msgstr "一片经过精心设计用十分复杂工艺制成的彩虹色纤维织 #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json msgid "nanowire battery" msgid_plural "nanowire batteries" -msgstr[0] "" +msgstr[0] "纳米线圈电池" #. ~ Description for {'str': 'nanowire battery', 'str_pl': 'nanowire #. batteries'} @@ -169137,7 +169390,7 @@ msgstr "一种能量密度很高的小型电池元件。" #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json msgid "ultracapacitor" msgid_plural "ultracapacitors" -msgstr[0] "" +msgstr[0] "超级电容" #. ~ Description for {'str': 'ultracapacitor'} #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json @@ -169149,7 +169402,7 @@ msgstr "一种由奇异原子化合物制成的超级电容,能储存大量的 #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json msgid "ultracapacitor array" msgid_plural "ultracapacitor arrays" -msgstr[0] "" +msgstr[0] "超级电容阵列" #. ~ Description for {'str': 'ultracapacitor array'} #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json @@ -169159,7 +169412,7 @@ msgstr "一个由经过精密调谐的超级电容组装而成的储能阵列。 #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json msgid "superconductive coil" msgid_plural "superconductive coils" -msgstr[0] "" +msgstr[0] "超导线圈" #. ~ Description for {'str': 'superconductive coil'} #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json @@ -169171,7 +169424,7 @@ msgstr "自缠绕而成的超导线圈能够控制电磁频谱以储存巨量的 #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json msgid "zero-point energy extractor" msgid_plural "zero-point energy extractors" -msgstr[0] "" +msgstr[0] "零点能提取器" #. ~ Description for {'str': 'zero-point energy extractor'} #: data/mods/Aftershock/items/crafting_scrap/energy_storage_scrap.json @@ -169183,7 +169436,7 @@ msgstr "一个复杂的时空网格把时空平面钉在多重超环面的表面 #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json msgid "high quality electromagnet" msgid_plural "high quality electromagnets" -msgstr[0] "" +msgstr[0] "高品质电磁铁" #. ~ Description for {'str': 'high quality electromagnet'} #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json @@ -169193,7 +169446,7 @@ msgstr "一个耐用的工厂生产的电磁铁。" #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json msgid "cryo electromagnet" msgid_plural "cryo electromagnets" -msgstr[0] "" +msgstr[0] "低温电磁铁" #. ~ Description for {'str': 'cryo electromagnet'} #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json @@ -169205,7 +169458,7 @@ msgstr "一个强大的低温超导电磁铁,必须保持在非常低的温度 #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json msgid "super conductive electromagnet" msgid_plural "super conductive electromagnets" -msgstr[0] "" +msgstr[0] "超导电磁铁" #. ~ Description for {'str': 'super conductive electromagnet'} #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json @@ -169215,7 +169468,7 @@ msgstr "一个由室温超导体制成的强力电磁铁。" #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json msgid "ferrofluid dynamo" msgid_plural "ferrofluid dynamos" -msgstr[0] "" +msgstr[0] "铁磁流体发电机" #. ~ Description for {'str': 'ferrofluid dynamo'} #: data/mods/Aftershock/items/crafting_scrap/magnet_scrap.json @@ -169227,7 +169480,7 @@ msgstr "黑色金属流体,和谐地流动变形成一个又一个分形形状 #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json msgid "composite alloy" msgid_plural "composite alloys" -msgstr[0] "" +msgstr[0] "复合合金" #. ~ Description for {'str': 'composite alloy'} #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json @@ -169237,7 +169490,7 @@ msgstr "由复合合金制成的各种废料。" #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json msgid "vacuum cast carbide" msgid_plural "vacuum cast carbides" -msgstr[0] "" +msgstr[0] "真空铸造碳化物" #. ~ Description for {'str': 'vacuum cast carbide'} #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json @@ -169247,7 +169500,7 @@ msgstr "由位于高地球轨道的锻造厂所铸造的有良好延展性的碳 #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json msgid "nanoprinted alloy" msgid_plural "nanoprinted alloys" -msgstr[0] "" +msgstr[0] "纳米打印合金" #. ~ Description for {'str': 'nanoprinted alloy'} #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json @@ -169259,7 +169512,7 @@ msgstr "一种通过在原子尺度上精确地分层放置不同的元素制造 #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json msgid "crystal forged neutrite" msgid_plural "crystal forged neutrites" -msgstr[0] "" +msgstr[0] "晶锻中子材料" #. ~ Description for {'str': 'crystal forged neutrite'} #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json @@ -169272,7 +169525,7 @@ msgstr "位于地核深层的巨大锻炉将氢气转化为燃烧的金属态, #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json msgid "phase uneven matter" msgid_plural "phase uneven matters" -msgstr[0] "" +msgstr[0] "相位不平衡物质" #. ~ Description for {'str': 'phase uneven matter'} #: data/mods/Aftershock/items/crafting_scrap/material_scrap.json @@ -169282,7 +169535,7 @@ msgstr "由多维度之间阈限空间凝结而成的物质材料。" #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json msgid "peripheral electrode" msgid_plural "peripheral electrodes" -msgstr[0] "" +msgstr[0] "外围电极" #. ~ Description for {'str': 'peripheral electrode'} #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json @@ -169294,7 +169547,7 @@ msgstr "一根带着夹子的细长电线,用来嵌入连接到人体四周细 #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json msgid "neural electrode" msgid_plural "neural electrodes" -msgstr[0] "" +msgstr[0] "神经电极" #. ~ Description for {'str': 'neural electrode'} #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json @@ -169306,7 +169559,7 @@ msgstr "一个有着许多金属针头的小型阵列,能让机器和人类大 #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json msgid "brain implant prod" msgid_plural "brain implant prods" -msgstr[0] "" +msgstr[0] "脑植入体刺针" #. ~ Description for {'str': 'brain implant prod'} #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json @@ -169318,7 +169571,7 @@ msgstr "一根外表有着复杂的金属刻蚀图案的针,与受体的胼胝 #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json msgid "artificial neural tissue" msgid_plural "artificial neural tissues" -msgstr[0] "" +msgstr[0] "人造神经组织" #. ~ Description for {'str': 'artificial neural tissue'} #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json @@ -169330,7 +169583,7 @@ msgstr "光子轴突的思维处理速度远远超过了原始的、基于化学 #: data/mods/Aftershock/items/crafting_scrap/neural_io_scrap.json msgid "neurosynaptic interface matrix" msgid_plural "neurosynaptic interface matrices" -msgstr[0] "" +msgstr[0] "神经突触界面矩阵" #. ~ Description for {'str': 'neurosynaptic interface matrix', 'str_pl': #. 'neurosynaptic interface matrices'} @@ -169344,7 +169597,7 @@ msgstr "一层人造神经元构成的膜包裹着大脑皮层,将机器和人 #: data/mods/Aftershock/items/gun/5x50.json msgid "eidolon derringer" msgid_plural "eidolon derringers" -msgstr[0] "" +msgstr[0] "伊多伦德林加手枪" #: data/mods/Aftershock/items/gun/5x50.json msgid "" @@ -169362,7 +169615,7 @@ msgstr "4 連發" #: data/mods/Modular_Turrets/roboguns.json msgid "base robogun" msgid_plural "base roboguns" -msgstr[0] "" +msgstr[0] "基础机器枪" #: data/mods/Aftershock/items/gun/advanced.json #: data/mods/Modular_Turrets/roboguns.json @@ -169398,7 +169651,7 @@ msgstr "帶有電磁脈衝電荷的 40 毫米榴彈。它會釋放出能夠損 #: data/mods/Aftershock/items/gun/laser.json msgid "wrist-stunner" msgid_plural "wrist-stunners" -msgstr[0] "" +msgstr[0] "眩晕机械手" #: data/mods/Aftershock/items/gun/laser.json msgid "" @@ -169410,7 +169663,7 @@ msgstr "从\"幽灵怪\"哨兵机器人上砍下来的一只机械手。 腕上 #: data/mods/Aftershock/items/gun/laser.json msgid "wrist-trilaser" msgid_plural "wrist-trilasers" -msgstr[0] "" +msgstr[0] "三管激光机械手" #: data/mods/Aftershock/items/gun/laser.json msgid "" @@ -169426,7 +169679,7 @@ msgstr "三管激光" #: data/mods/Aftershock/items/gun/projectile.json msgid "bionic skullgun" msgid_plural "bionic skullguns" -msgstr[0] "" +msgstr[0] "生化头骨枪" #: data/mods/Aftershock/items/gun/projectile.json msgid "Bionic one-shot subdermal .40 pistol integrated with your head." @@ -169652,7 +169905,7 @@ msgstr "沃特利家族殡仪馆服务。已为新英格兰服务了三百年。 #: data/mods/Aftershock/mobs/PrepPhyle_mobs.json msgid "Cyber Mastiff" msgid_plural "Cyber Mastifs" -msgstr[0] "" +msgstr[0] "赛博獒犬" #. ~ Description for {'str': 'Cyber Mastiff', 'str_pl': 'Cyber Mastifs'} #: data/mods/Aftershock/mobs/PrepPhyle_mobs.json @@ -169665,7 +169918,7 @@ msgstr "一条大白熊犬和高加索犬的混血犬,体内安装了许多生 #: data/mods/Aftershock/mobs/PrepPhyle_mobs.json msgid "Cyber Mastiff puppy" msgid_plural "Cyber Mastiff puppies" -msgstr[0] "" +msgstr[0] "赛博獒犬幼犬" #. ~ Description for {'str': 'Cyber Mastiff puppy', 'str_pl': 'Cyber Mastiff #. puppies'} @@ -169678,7 +169931,7 @@ msgstr "一只可爱而无助的幼年赛博獒犬。驯服起来比一只成年 #: data/mods/Aftershock/mobs/robots.json msgid "brain blaster" msgid_plural "brain blasters" -msgstr[0] "" +msgstr[0] "脑熔炮塔" #. ~ Description for {'str': 'brain blaster'} #: data/mods/Aftershock/mobs/robots.json @@ -169691,7 +169944,7 @@ msgstr "米·戈已经在这里设置了一些防御系统。这个由机械和 #: data/mods/Aftershock/mobs/robots.json msgid "Whately family brain blaster" msgid_plural "Whately family brain blasters" -msgstr[0] "" +msgstr[0] "沃特利脑熔炮塔" #. ~ Description for {'str': 'Whately family brain blaster'} #: data/mods/Aftershock/mobs/robots.json @@ -169715,7 +169968,7 @@ msgstr "" #: data/mods/Aftershock/mobs/robots.json msgid "Wraitheon Sentinel-lx" msgid_plural "Wraitheon Sentinel-lxs" -msgstr[0] "" +msgstr[0] "幽灵怪哨兵-lx型机器人" #. ~ Description for {'str': 'Wraitheon Sentinel-lx'} #: data/mods/Aftershock/mobs/robots.json @@ -169730,7 +169983,7 @@ msgstr "" #: data/mods/Aftershock/mobs/robots.json msgid "bloodhound drone" msgid_plural "bloodhound drones" -msgstr[0] "" +msgstr[0] "猎犬无人机" #. ~ Description for {'str': 'bloodhound drone'} #: data/mods/Aftershock/mobs/robots.json @@ -170032,6 +170285,12 @@ msgid "" "constant jet of warm air to heat an enclosed space." msgstr "一台经过改装的眼球无人机,用来当作浮空移动的加热器使用。它持续不断地朝四周释放暖气来加热封闭空间。" +#: data/mods/Aftershock/mobs/species.json +msgid "intelligent animal" +msgid_plural "intelligent animals" +msgstr[0] "" + +#. ~ Description for {'str': 'intelligent animal'} #: data/mods/Aftershock/mobs/species.json msgid "an intelligent animal created by man before the Cataclysm" msgstr "基因擢升人" @@ -170039,7 +170298,7 @@ msgstr "基因擢升人" #: data/mods/Aftershock/mobs/turrets.json msgid "x-ray laser turret" msgid_plural "x-ray laser turrets" -msgstr[0] "" +msgstr[0] "X射线炮塔" #. ~ Description for {'str': 'x-ray laser turret'} #: data/mods/Aftershock/mobs/turrets.json @@ -170052,7 +170311,7 @@ msgstr "TX-5LR \"地狱犬\"型激光炮塔是其前身的升级版。它的特 #: data/mods/Aftershock/mobs/uplifted_monsters.json msgid "Schwarz Walder" msgid_plural "Schwarz Walders" -msgstr[0] "" +msgstr[0] "黑森林熊人" #. ~ Description for {'str': 'Schwarz Walder'} #: data/mods/Aftershock/mobs/uplifted_monsters.json @@ -170068,7 +170327,7 @@ msgstr "" #: data/mods/Aftershock/mobs/uplifted_monsters.json msgid "Schwarz Walder cub" msgid_plural "Schwarz Walder cubs" -msgstr[0] "" +msgstr[0] "黑森林熊人幼兽" #. ~ Description for {'str': 'Schwarz Walder cub'} #: data/mods/Aftershock/mobs/uplifted_monsters.json @@ -170080,7 +170339,7 @@ msgstr "一只黑森林熊人幼兽。如果你发现了一只黑森林熊人幼 #: data/mods/Aftershock/mobs/uplifted_monsters.json msgid "infeme" msgid_plural "infemes" -msgstr[0] "" +msgstr[0] "因非玛人" #. ~ Description for {'str': 'infeme'} #: data/mods/Aftershock/mobs/uplifted_monsters.json @@ -170123,7 +170382,7 @@ msgstr "" #: data/mods/Aftershock/mobs/zombies.json msgid "Haunting Forest Walker" msgid_plural "Haunting Forest Walkers" -msgstr[0] "" +msgstr[0] "恐怖森林丧尸" #. ~ Description for {'str': 'Haunting Forest Walker'} #: data/mods/Aftershock/mobs/zombies.json @@ -170136,7 +170395,7 @@ msgstr "这只体积巨大的丧尸身上满是伤口和破碎的毛皮。也许 #: data/mods/Aftershock/mobs/zombies.json msgid "rotting grodd" msgid_plural "rotting grodds" -msgstr[0] "" +msgstr[0] "腐烂格鲁德丧尸" #. ~ Description for {'str': 'rotting grodd'} #: data/mods/Aftershock/mobs/zombies.json @@ -170148,7 +170407,7 @@ msgstr "在脑海里想象一只大猩猩。然后再想象一下它死了,腐 #: data/mods/Aftershock/mobs/zombies.json msgid "Ghoulodon" msgid_plural "Ghoulodons" -msgstr[0] "" +msgstr[0] "长毛丧尸王" #. ~ Description for {'str': 'Ghoulodon'} #: data/mods/Aftershock/mobs/zombies.json @@ -173449,7 +173708,7 @@ msgstr "堅固的輕型框架,由鈦製成。用於製作。" #: data/mods/Aftershock/vehicles/part_items.json msgid "ultralight foldable frame" msgid_plural "ultralight foldable frames" -msgstr[0] "" +msgstr[0] "折叠超轻车架" #. ~ Description for {'str': 'ultralight foldable frame'} #: data/mods/Aftershock/vehicles/part_items.json @@ -173700,7 +173959,7 @@ msgstr "一种特异型合金弹丸,设计目的为超越普通铅弹飞行速 #: data/mods/CRT_EXPANSION/items/crt_ammo.json msgid "pulse round" msgid_plural "pulse rounds" -msgstr[0] "" +msgstr[0] "脉冲弹" #. ~ Description for pulse round #: data/mods/CRT_EXPANSION/items/crt_ammo.json @@ -174195,7 +174454,7 @@ msgstr "燃爆" #: data/mods/CRT_EXPANSION/items/crt_gun.json msgid "pellet gun" msgid_plural "pellet guns" -msgstr[0] "" +msgstr[0] "弹丸枪" #: data/mods/CRT_EXPANSION/items/crt_gun.json msgid "" @@ -174272,7 +174531,7 @@ msgstr "电磁场锯" #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "Underslung flare launcher" msgid_plural "Underslung flare launchers" -msgstr[0] "" +msgstr[0] "下挂式信号弹发射器" #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "" @@ -174283,7 +174542,7 @@ msgstr "一个下挂式信号弹发射器。由于它所处的尴尬位置,相 #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "CQB SI shotgun" msgid_plural "CQB SI shotguns" -msgstr[0] "" +msgstr[0] "CQB 运动霰弹枪" #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "" @@ -174294,7 +174553,7 @@ msgstr "集成在枪械上的下挂式霰弹枪,能容纳1发霰弹。无法 #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "butt hook stock" msgid_plural "butt hook stocks" -msgstr[0] "" +msgstr[0] "折叠式带钩枪托" #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "" @@ -174306,7 +174565,7 @@ msgstr "一个军用级的枪托,能够折叠起来减少枪械体积。它的 #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "diffracting lens" msgid_plural "diffracting lenses" -msgstr[0] "" +msgstr[0] "衍射透镜" #: data/mods/CRT_EXPANSION/items/crt_gunmods.json msgid "" @@ -175536,7 +175795,7 @@ msgstr "融入阴影。" #: data/mods/CRT_EXPANSION/mutations/vamp_mut_cat.json msgid "vampire mutagen" msgid_plural "vampire mutagens" -msgstr[0] "" +msgstr[0] "吸血鬼诱变剂" #. ~ Description for vampire mutagen #. ~ Description for wendigo mutagen @@ -175548,7 +175807,7 @@ msgstr "混合诱变剂,仅简单标记着 'C.R.I.T R&D.'。" #: data/mods/CRT_EXPANSION/mutations/vamp_mut_cat.json msgid "vampire serum" msgid_plural "vampire serums" -msgstr[0] "" +msgstr[0] "吸血鬼诱变血清" #. ~ Description for vampire serum #: data/mods/CRT_EXPANSION/mutations/vamp_mut_cat.json @@ -175629,12 +175888,12 @@ msgstr "回归自然。" #: data/mods/CRT_EXPANSION/mutations/wendigo_mut_cat.json msgid "wendigo mutagen" msgid_plural "wendigo mutagens" -msgstr[0] "" +msgstr[0] "雪怪诱变剂" #: data/mods/CRT_EXPANSION/mutations/wendigo_mut_cat.json msgid "wendigo serum" msgid_plural "wendigo serums" -msgstr[0] "" +msgstr[0] "雪怪诱变血清" #. ~ Description for wendigo serum #: data/mods/CRT_EXPANSION/mutations/wendigo_mut_cat.json @@ -176232,7 +176491,7 @@ msgstr "增加了更多自制的火器和火药。" #: data/mods/CrazyCataclysm/crazy_aperturepotato.json msgid "companion potato" msgid_plural "companion potatoes" -msgstr[0] "" +msgstr[0] "马铃薯娃娃" #. ~ Description for {'str': 'companion potato', 'str_pl': 'companion #. potatoes'} @@ -176245,7 +176504,7 @@ msgstr "看上去像是些基因工程生命和操作系统,被连在一个马 #: data/mods/CrazyCataclysm/crazy_comestibles.json msgid "SpOreos" msgid_plural "SpOreos" -msgstr[0] "" +msgstr[0] "孢子奥利奥" #. ~ Description for {'str_sp': 'SpOreos'} #: data/mods/CrazyCataclysm/crazy_comestibles.json @@ -176298,7 +176557,7 @@ msgstr "" #: data/mods/CrazyCataclysm/crazy_items.json msgid "Ionic Overload Generator" msgid_plural "Ionic Overload Generators" -msgstr[0] "" +msgstr[0] "离子过载发生器" #: data/mods/CrazyCataclysm/crazy_items.json msgid "" @@ -176312,7 +176571,7 @@ msgstr "" #: data/mods/CrazyCataclysm/crazy_items.json msgid "Yeet Cannon" msgid_plural "Yeet Cannons" -msgstr[0] "" +msgstr[0] "Biubiu炮" #: data/mods/CrazyCataclysm/crazy_items.json msgid "" @@ -178423,7 +178682,7 @@ msgstr "一滩恐龙粪便,可以用来制造不错的肥料。" #: data/mods/DinoMod/items/books.json msgid "Kiernan's notes" msgid_plural "copies of Kiernan's notes" -msgstr[0] "" +msgstr[0] "基尔南的笔记" #. ~ Description for {'str': "Kiernan's notes", 'str_pl': "copies of Kiernan's #. notes"} @@ -178588,7 +178847,7 @@ msgstr "一只巨型蜥脚恐龙的胃囊,清洗干净之后用绳子扎好。 #: data/mods/DinoMod/items/egg.json msgid "dinosaur egg" msgid_plural "dinosaur eggs" -msgstr[0] "" +msgstr[0] "恐龙蛋" #. ~ Description for dinosaur egg #: data/mods/DinoMod/items/egg.json @@ -178598,7 +178857,7 @@ msgstr "一颗苍白的圆形恐龙蛋。" #: data/mods/DinoMod/items/egg.json msgid "small dinosaur egg" msgid_plural "small dinosaur eggs" -msgstr[0] "" +msgstr[0] "小型恐龙蛋" #. ~ Description for small dinosaur egg #: data/mods/DinoMod/items/egg.json @@ -178608,7 +178867,7 @@ msgstr "一只较小的恐龙产下的苍白的圆形的蛋。" #: data/mods/DinoMod/items/egg.json msgid "large dinosaur egg" msgid_plural "large dinosaur eggs" -msgstr[0] "" +msgstr[0] "大型恐龙蛋" #. ~ Description for large dinosaur egg #: data/mods/DinoMod/items/egg.json @@ -178633,22 +178892,22 @@ msgstr "一只大恐龙产下的苍白的足球形状的蛋。" #: data/mods/DinoMod/items/egg.json msgid "coelophysis egg" msgid_plural "coelophysis eggs" -msgstr[0] "" +msgstr[0] "腔骨龙蛋" #: data/mods/DinoMod/items/egg.json msgid "dilophosaurus egg" msgid_plural "dilophosaurus eggs" -msgstr[0] "" +msgstr[0] "双脊龙蛋" #: data/mods/DinoMod/items/egg.json msgid "ceratosaurus egg" msgid_plural "ceratosaurus eggs" -msgstr[0] "" +msgstr[0] "角鼻龙蛋" #: data/mods/DinoMod/items/egg.json msgid "spinosaurus egg" msgid_plural "spinosaurus eggs" -msgstr[0] "" +msgstr[0] "棘龙蛋" #: data/mods/DinoMod/items/egg.json msgid "torvosaurus egg" @@ -178658,17 +178917,17 @@ msgstr[0] "蛮龙蛋" #: data/mods/DinoMod/items/egg.json msgid "allosaurus egg" msgid_plural "allosaurus eggs" -msgstr[0] "" +msgstr[0] "异特龙蛋" #: data/mods/DinoMod/items/egg.json msgid "acrocanthosaurus egg" msgid_plural "acrocanthosaurus eggs" -msgstr[0] "" +msgstr[0] "高棘龙蛋" #: data/mods/DinoMod/items/egg.json msgid "siats egg" msgid_plural "siats eggs" -msgstr[0] "" +msgstr[0] "西雅茨龙蛋" #: data/mods/DinoMod/items/egg.json msgid "dryptosaurus egg" @@ -178688,12 +178947,12 @@ msgstr[0] "戈尔冈龙蛋" #: data/mods/DinoMod/items/egg.json msgid "albertosaurus egg" msgid_plural "albertosaurus eggs" -msgstr[0] "" +msgstr[0] "阿尔伯塔龙蛋" #: data/mods/DinoMod/items/egg.json msgid "qianzhousaurus egg" msgid_plural "qianzhousaurus eggs" -msgstr[0] "" +msgstr[0] "虔州龙蛋" #: data/mods/DinoMod/items/egg.json msgid "nanuqsaurus egg" @@ -178708,17 +178967,17 @@ msgstr[0] "惧龙蛋" #: data/mods/DinoMod/items/egg.json msgid "tyrannosaurus egg" msgid_plural "tyrannosaurus eggs" -msgstr[0] "" +msgstr[0] "霸王龙蛋" #: data/mods/DinoMod/items/egg.json msgid "compsognathus egg" msgid_plural "compsognathus eggs" -msgstr[0] "" +msgstr[0] "美颌龙蛋" #: data/mods/DinoMod/items/egg.json msgid "gallimimus egg" msgid_plural "gallimimus eggs" -msgstr[0] "" +msgstr[0] "似鸡龙蛋" #: data/mods/DinoMod/items/egg.json msgid "struthiomimus egg" @@ -178738,7 +178997,7 @@ msgstr[0] "亚伯达爪龙蛋" #: data/mods/DinoMod/items/egg.json msgid "nothronychus egg" msgid_plural "nothronychus eggs" -msgstr[0] "" +msgstr[0] "懒爪龙蛋" #: data/mods/DinoMod/items/egg.json msgid "anzu egg" @@ -178753,17 +179012,17 @@ msgstr[0] "蜥鸟盗龙蛋" #: data/mods/DinoMod/items/egg.json msgid "velociraptor egg" msgid_plural "velociraptor eggs" -msgstr[0] "" +msgstr[0] "伶盗龙蛋" #: data/mods/DinoMod/items/egg.json msgid "deinonychus egg" msgid_plural "deinonychus eggs" -msgstr[0] "" +msgstr[0] "恐爪龙蛋" #: data/mods/DinoMod/items/egg.json msgid "utahraptor egg" msgid_plural "utahraptor eggs" -msgstr[0] "" +msgstr[0] "犹他盗龙蛋" #: data/mods/DinoMod/items/egg.json msgid "dromaeosaurus egg" @@ -178778,7 +179037,7 @@ msgstr[0] "伤齿龙蛋" #: data/mods/DinoMod/items/egg.json msgid "eoraptor egg" msgid_plural "eoraptor eggs" -msgstr[0] "" +msgstr[0] "始盗龙蛋" #: data/mods/DinoMod/items/egg.json msgid "sarahsaurus egg" @@ -178803,22 +179062,22 @@ msgstr[0] "简棘龙蛋" #: data/mods/DinoMod/items/egg.json msgid "amargasaurus egg" msgid_plural "amargasaurus eggs" -msgstr[0] "" +msgstr[0] "阿马加龙蛋" #: data/mods/DinoMod/items/egg.json msgid "apatosaurus egg" msgid_plural "apatosaurus eggs" -msgstr[0] "" +msgstr[0] "迷惑龙蛋" #: data/mods/DinoMod/items/egg.json msgid "brontosaurus egg" msgid_plural "brontosaurus eggs" -msgstr[0] "" +msgstr[0] "雷龙蛋" #: data/mods/DinoMod/items/egg.json msgid "diplodocus egg" msgid_plural "diplodocus eggs" -msgstr[0] "" +msgstr[0] "梁龙蛋" #: data/mods/DinoMod/items/egg.json msgid "barosaurus egg" @@ -178828,27 +179087,27 @@ msgstr[0] "巴洛龙蛋" #: data/mods/DinoMod/items/egg.json msgid "camarasaurus egg" msgid_plural "camarasaurus eggs" -msgstr[0] "" +msgstr[0] "圆顶龙蛋" #: data/mods/DinoMod/items/egg.json msgid "brachiosaurus egg" msgid_plural "brachiosaurus eggs" -msgstr[0] "" +msgstr[0] "腕龙蛋" #: data/mods/DinoMod/items/egg.json msgid "alamosaurus egg" msgid_plural "alamosaurus eggs" -msgstr[0] "" +msgstr[0] "阿拉摩龙蛋" #: data/mods/DinoMod/items/egg.json msgid "scutellosaurus egg" msgid_plural "scutellosaurus eggs" -msgstr[0] "" +msgstr[0] "小盾龙蛋" #: data/mods/DinoMod/items/egg.json msgid "stegosaurus egg" msgid_plural "stegosaurus eggs" -msgstr[0] "" +msgstr[0] "剑龙蛋" #: data/mods/DinoMod/items/egg.json msgid "hesperosaurus egg" @@ -178873,7 +179132,7 @@ msgstr[0] "蜥结龙蛋" #: data/mods/DinoMod/items/egg.json msgid "nodosaurus egg" msgid_plural "nodosaurus eggs" -msgstr[0] "" +msgstr[0] "结节龙蛋" #: data/mods/DinoMod/items/egg.json msgid "panoplosaurus egg" @@ -178883,7 +179142,7 @@ msgstr[0] "胄甲龙蛋" #: data/mods/DinoMod/items/egg.json msgid "edmontonia egg" msgid_plural "edmontonia eggs" -msgstr[0] "" +msgstr[0] "埃德蒙顿甲龙蛋" #: data/mods/DinoMod/items/egg.json msgid "zuul egg" @@ -178893,12 +179152,12 @@ msgstr[0] "祖鲁龙蛋" #: data/mods/DinoMod/items/egg.json msgid "dyoplosaurus egg" msgid_plural "dyoplosaurus eggs" -msgstr[0] "" +msgstr[0] "倍甲龙蛋" #: data/mods/DinoMod/items/egg.json msgid "ankylosaurus egg" msgid_plural "ankylosaurus eggs" -msgstr[0] "" +msgstr[0] "甲龙蛋" #: data/mods/DinoMod/items/egg.json msgid "euoplocephalus egg" @@ -178923,7 +179182,7 @@ msgstr[0] "橡树龙蛋" #: data/mods/DinoMod/items/egg.json msgid "camptosaurus egg" msgid_plural "camptosaurus eggs" -msgstr[0] "" +msgstr[0] "弯龙蛋" #: data/mods/DinoMod/items/egg.json msgid "hadrosaurus egg" @@ -178933,7 +179192,7 @@ msgstr[0] "鸭嘴龙蛋" #: data/mods/DinoMod/items/egg.json msgid "maiasaura egg" msgid_plural "maiasaura eggs" -msgstr[0] "" +msgstr[0] "慈母龙蛋" #: data/mods/DinoMod/items/egg.json msgid "gryposaurus egg" @@ -178953,12 +179212,12 @@ msgstr[0] "龙栉龙蛋" #: data/mods/DinoMod/items/egg.json msgid "edmontosaurus egg" msgid_plural "edmontosaurus eggs" -msgstr[0] "" +msgstr[0] "埃德蒙顿龙蛋" #: data/mods/DinoMod/items/egg.json msgid "parasaurolophus egg" msgid_plural "parasaurolophus eggs" -msgstr[0] "" +msgstr[0] "副栉龙蛋" #: data/mods/DinoMod/items/egg.json msgid "lambeosaurus egg" @@ -178968,7 +179227,7 @@ msgstr[0] "赖氏龙蛋" #: data/mods/DinoMod/items/egg.json msgid "corythosaurus egg" msgid_plural "corythosaurus eggs" -msgstr[0] "" +msgstr[0] "冠龙蛋" #: data/mods/DinoMod/items/egg.json msgid "hypacrosaurus egg" @@ -178983,7 +179242,7 @@ msgstr[0] "顶角龙蛋" #: data/mods/DinoMod/items/egg.json msgid "pachycephalosaurus egg" msgid_plural "pachycephalosaurus eggs" -msgstr[0] "" +msgstr[0] "厚头龙蛋" #: data/mods/DinoMod/items/egg.json msgid "aquilops egg" @@ -179023,7 +179282,7 @@ msgstr[0] "河神龙蛋" #: data/mods/DinoMod/items/egg.json msgid "pachyrhinosaurus egg" msgid_plural "pachyrhinosaurus eggs" -msgstr[0] "" +msgstr[0] "厚鼻龙蛋" #: data/mods/DinoMod/items/egg.json msgid "chasmosaurus egg" @@ -179033,22 +179292,22 @@ msgstr[0] "开角龙蛋" #: data/mods/DinoMod/items/egg.json msgid "pentaceratops egg" msgid_plural "pentaceratops eggs" -msgstr[0] "" +msgstr[0] "五角龙蛋" #: data/mods/DinoMod/items/egg.json msgid "kosmoceratops egg" msgid_plural "kosmoceratops eggs" -msgstr[0] "" +msgstr[0] "科斯莫角龙蛋" #: data/mods/DinoMod/items/egg.json msgid "torosaurus egg" msgid_plural "torosaurus eggs" -msgstr[0] "" +msgstr[0] "牛角龙蛋" #: data/mods/DinoMod/items/egg.json msgid "triceratops egg" msgid_plural "triceratops eggs" -msgstr[0] "" +msgstr[0] "三角龙蛋" #: data/mods/DinoMod/items/egg.json msgid "nanosaurus egg" @@ -179068,17 +179327,17 @@ msgstr[0] "奇异龙蛋" #: data/mods/DinoMod/items/egg.json msgid "dimorphodon egg" msgid_plural "dimorphodon eggs" -msgstr[0] "" +msgstr[0] "双型齿翼龙蛋" #: data/mods/DinoMod/items/egg.json msgid "pteranodon egg" msgid_plural "pteranodon eggs" -msgstr[0] "" +msgstr[0] "无齿翼龙蛋" #: data/mods/DinoMod/items/egg.json msgid "quetzalcoatlus egg" msgid_plural "quetzalcoatlus eggs" -msgstr[0] "" +msgstr[0] "风神翼龙蛋" #: data/mods/DinoMod/items/egg.json msgid "small boiled dinosaur egg" @@ -179150,12 +179409,12 @@ msgstr[0] "食肉龙头骨盔" #: data/mods/DinoMod/items/items.json msgid "PRELIMINARY REPORT: IMMERSION-30D" msgid_plural "PRELIMINARY REPORT: IMMERSION-30Ds" -msgstr[0] "" +msgstr[0] "初步报告:沉浸-30Ds" #: data/mods/DinoMod/items/laser_items.json msgid "2-DINO-A7 laser rifle" msgid_plural "2-DINO-A7 laser rifles" -msgstr[0] "" +msgstr[0] "2-DINO-A7 激光步枪" #: data/mods/DinoMod/items/laser_items.json msgid "" @@ -179170,7 +179429,7 @@ msgstr "" #: data/mods/DinoMod/items/mutagen.json msgid "tyrant serum" msgid_plural "tyrant serums" -msgstr[0] "" +msgstr[0] "暴龙诱变血清" #. ~ Description for tyrant serum #: data/mods/DinoMod/items/mutagen.json @@ -179182,7 +179441,7 @@ msgstr "超浓缩的诱变剂,像是儿童玩具里的黏液。你需要一根 #: data/mods/DinoMod/items/mutagen.json msgid "tyrant mutagen" msgid_plural "tyrant mutagens" -msgstr[0] "" +msgstr[0] "暴龙诱变剂" #. ~ Description for tyrant mutagen #: data/mods/DinoMod/items/mutagen.json @@ -179194,12 +179453,12 @@ msgstr "一种极度罕见的混合诱变剂,闻上去就像是血,一团带 #: data/mods/DinoMod/items/mutagen.json msgid "stego serum" msgid_plural "stego serums" -msgstr[0] "" +msgstr[0] "剑龙诱变血清" #: data/mods/DinoMod/items/mutagen.json msgid "stego mutagen" msgid_plural "stego mutagens" -msgstr[0] "" +msgstr[0] "剑龙诱变剂" #: data/mods/DinoMod/items/petfoods.json msgid "wet dog food" @@ -179428,7 +179687,7 @@ msgstr "一套厚厚的皮甲,关键部位有精心放置的青铜板,专门 #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "elephant armor" msgid_plural "elephant armors" -msgstr[0] "" +msgstr[0] "象铠" #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "Kevlar-lined elephant-sized peto" @@ -179446,7 +179705,7 @@ msgstr "一套由棉布、皮革和厚厚的凯夫拉内衬制成的沉重的床 #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "biosilicified chitin elephant armor" msgid_plural "biosilicified chitin elephant armors" -msgstr[0] "" +msgstr[0] "硅化甲壳象铠" #. ~ Description for {'str': 'biosilicified chitin elephant armor'} #: data/mods/DinoMod/items/pets_elephant_armor.json @@ -179460,7 +179719,7 @@ msgstr "" #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "chitin elephant armor" msgid_plural "chitin elephant armors" -msgstr[0] "" +msgstr[0] "甲壳象铠" #. ~ Description for {'str': 'chitin elephant armor'} #: data/mods/DinoMod/items/pets_elephant_armor.json @@ -179473,7 +179732,7 @@ msgstr "" #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "chainmail elephant armor" msgid_plural "chainmail elephant armors" -msgstr[0] "" +msgstr[0] "锁环象铠" #. ~ Description for {'str': 'chainmail elephant armor'} #: data/mods/DinoMod/items/pets_elephant_armor.json @@ -179485,7 +179744,7 @@ msgstr "一套厚厚的铁环链甲,专门为保护大象打造。你可以将 #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "boiled leather elephant barding with caparison" msgid_plural "boiled leather elephant bardings with caparison" -msgstr[0] "" +msgstr[0] "华丽皮革象铠" #. ~ Description for {'str': 'boiled leather elephant barding with caparison', #. 'str_pl': 'boiled leather elephant bardings with caparison'} @@ -179551,7 +179810,7 @@ msgstr "" #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "boiled leather elephant barding with bones" msgid_plural "boiled leather elephant bardings with bones" -msgstr[0] "" +msgstr[0] "骨钉皮革象铠" #. ~ Description for {'str': 'boiled leather elephant barding with bones', #. 'str_pl': 'boiled leather elephant bardings with bones'} @@ -179565,7 +179824,7 @@ msgstr "一套鞣制皮革制成的象铠,上面附加了许多装饰性的骨 #: data/mods/DinoMod/items/pets_elephant_armor.json msgid "elephant rain sheet" msgid_plural "elephant rain sheets" -msgstr[0] "" +msgstr[0] "象用雨衣" #. ~ Description for {'str': 'elephant rain sheet'} #: data/mods/DinoMod/items/pets_elephant_armor.json @@ -179823,6 +180082,12 @@ msgstr "一套厚厚的皮甲,关键部位有精心放置的青铜甲,专门 msgid "DinoLab Operating Theater Access Control" msgstr "恐龙实验室手术中心控制台" +#: data/mods/DinoMod/monsters/dinosaur.json +msgid "dinosaur" +msgid_plural "dinosaurs" +msgstr[0] "" + +#. ~ Description for {'str': 'dinosaur'} #: data/mods/DinoMod/monsters/dinosaur.json msgid "a dinosaur" msgstr "恐龙" @@ -180916,7 +181181,7 @@ msgstr "一只巨型水生恐龙,有一栋小房子那么高,长着凶猛的 #: data/mods/DinoMod/monsters/dinosaur_CBM.json msgid "Spinosaurus bio-operator" msgid_plural "Spinosaurus bio-operator" -msgstr[0] "" +msgstr[0] "生化棘龙" #. ~ Description for {'str_sp': 'Spinosaurus bio-operator'} #: data/mods/DinoMod/monsters/dinosaur_CBM.json @@ -180931,7 +181196,7 @@ msgstr "" #: data/mods/DinoMod/monsters/dinosaur_CBM.json msgid "Gallimimus bio-operator" msgid_plural "Gallimimus bio-operator" -msgstr[0] "" +msgstr[0] "生化似鸡龙" #. ~ Description for {'str_sp': 'Gallimimus bio-operator'} #: data/mods/DinoMod/monsters/dinosaur_CBM.json @@ -180943,7 +181208,7 @@ msgstr "一只快速移动的有羽毛的双足恐龙,上面点缀着噼啪作 #: data/mods/DinoMod/monsters/dinosaur_CBM.json msgid "Pachycephalosaurus bio-operator" msgid_plural "Pachycephalosaurus bio-operator" -msgstr[0] "" +msgstr[0] "生化厚头龙" #. ~ Description for {'str_sp': 'Pachycephalosaurus bio-operator'} #: data/mods/DinoMod/monsters/dinosaur_CBM.json @@ -180955,7 +181220,7 @@ msgstr "一只长着坚硬圆头的有羽毛的双足恐龙,上面点缀着噼 #: data/mods/DinoMod/monsters/dinosaur_CBM.json msgid "Triceratops bio-operator" msgid_plural "Triceratops bio-operator" -msgstr[0] "" +msgstr[0] "生化三角龙" #. ~ Description for {'str_sp': 'Triceratops bio-operator'} #: data/mods/DinoMod/monsters/dinosaur_CBM.json @@ -180967,7 +181232,7 @@ msgstr "一只巨大的三角四足恐龙,上面点缀着噼啪作响的生化 #: data/mods/DinoMod/monsters/dinosaur_CBM.json msgid "Velociraptor bio-operator" msgid_plural "Velociraptor bio-operator" -msgstr[0] "" +msgstr[0] "生化伶盗龙" #. ~ Description for {'str_sp': 'Velociraptor bio-operator'} #: data/mods/DinoMod/monsters/dinosaur_CBM.json @@ -180979,7 +181244,7 @@ msgstr "一只有羽毛的小型双足恐龙,上面点缀着噼啪作响的生 #: data/mods/DinoMod/monsters/dinosaur_CBM.json msgid "Deinonychus bio-operator" msgid_plural "Deinonychus bio-operator" -msgstr[0] "" +msgstr[0] "生化恐爪龙" #. ~ Description for {'str_sp': 'Deinonychus bio-operator'} #: data/mods/DinoMod/monsters/dinosaur_CBM.json @@ -180991,7 +181256,7 @@ msgstr "一具体表覆盖着羽毛的中型两足恐龙,它体内的生化插 #: data/mods/DinoMod/monsters/dinosaur_CBM.json msgid "Dimorphodon bio-operator" msgid_plural "Dimorphodon bio-operator" -msgstr[0] "" +msgstr[0] "生化双型齿翼龙" #. ~ Description for {'str_sp': 'Dimorphodon bio-operator'} #: data/mods/DinoMod/monsters/dinosaur_CBM.json @@ -182055,27 +182320,27 @@ msgstr "" #: data/mods/DinoMod/monsters/hatchling.json msgid "magenta and green hatchling" msgid_plural "magenta and green hatchlings" -msgstr[0] "" +msgstr[0] "紫绿色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "brown and white hatchling" msgid_plural "brown and white hatchlings" -msgstr[0] "" +msgstr[0] "棕白色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "red and white hatchling" msgid_plural "red and white hatchlings" -msgstr[0] "" +msgstr[0] "红白色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "light red and white hatchling" msgid_plural "light red and white hatchlings" -msgstr[0] "" +msgstr[0] "浅红白色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "greenish yellow hatchling" msgid_plural "greenish yellow hatchlings" -msgstr[0] "" +msgstr[0] "黄绿色恐龙幼仔" #. ~ Description for greenish yellow hatchling #: data/mods/DinoMod/monsters/hatchling.json @@ -182087,42 +182352,42 @@ msgstr "一只体型很小的恐龙幼仔,长着大而闪亮的眼睛,太小 #: data/mods/DinoMod/monsters/hatchling.json msgid "light green and yellow hatchling" msgid_plural "light green and yellow hatchlings" -msgstr[0] "" +msgstr[0] "浅黄绿色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "green and magenta hatchling" msgid_plural "green and magenta hatchlings" -msgstr[0] "" +msgstr[0] "绿紫色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "dark gray and yellow hatchling" msgid_plural "dark gray and yellow hatchlings" -msgstr[0] "" +msgstr[0] "深灰黄色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "red and green hatchling" msgid_plural "red and green hatchlings" -msgstr[0] "" +msgstr[0] "红绿色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "dark gray and white hatchling" msgid_plural "dark gray and white hatchlings" -msgstr[0] "" +msgstr[0] "深灰白色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "brown and magenta hatchling" msgid_plural "brown and magenta hatchlings" -msgstr[0] "" +msgstr[0] "棕紫色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "dark gray and magenta hatchling" msgid_plural "dark gray and magenta hatchlings" -msgstr[0] "" +msgstr[0] "深灰紫色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "light green and magenta hatchling" msgid_plural "light green and magenta hatchlings" -msgstr[0] "" +msgstr[0] "浅绿紫色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "green and purple hatchling" @@ -182132,7 +182397,7 @@ msgstr[0] "绿紫色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "light gray and yellow hatchling" msgid_plural "light gray and yellow hatchlings" -msgstr[0] "" +msgstr[0] "浅灰黄色恐龙幼仔" #: data/mods/DinoMod/monsters/hatchling.json msgid "mosasaurus neonate" @@ -182163,7 +182428,7 @@ msgstr[0] "角鼻龙幼仔" #: data/mods/DinoMod/monsters/juvenile.json msgid "spinosaurus juvenile" msgid_plural "spinosaurus juveniles" -msgstr[0] "" +msgstr[0] "棘龙幼仔" #. ~ Description for spinosaurus juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -182310,7 +182575,7 @@ msgstr "一只长着大而锋利的牙齿的大型食肉恐龙幼仔。" #: data/mods/DinoMod/monsters/juvenile.json msgid "greenish yellow two-legged juvenile" msgid_plural "greenish yellow two-legged juveniles" -msgstr[0] "" +msgstr[0] "黄绿色双足恐龙幼仔" #. ~ Description for greenish yellow two-legged juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -182322,7 +182587,7 @@ msgstr "一只小型双足恐龙幼仔,长着大而闪亮的眼睛,太小了 #: data/mods/DinoMod/monsters/juvenile.json msgid "green and magenta two-legged juvenile" msgid_plural "green and magenta two-legged juveniles" -msgstr[0] "" +msgstr[0] "绿紫色双足恐龙幼仔" #. ~ Description for green and magenta two-legged juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -182341,7 +182606,7 @@ msgstr "一只小型双足恐龙幼仔,长着大而闪亮的眼睛和喙,太 #: data/mods/DinoMod/monsters/juvenile.json msgid "red and green two-legged juvenile" msgid_plural "red and green two-legged juveniles" -msgstr[0] "" +msgstr[0] "红绿色双足恐龙幼仔" #. ~ Description for red and green two-legged juvenile #. ~ Description for gray and white two-legged juvenile @@ -182354,7 +182619,7 @@ msgstr "一只小型双足食肉恐龙幼仔,长着大而闪亮的眼睛,太 #: data/mods/DinoMod/monsters/juvenile.json msgid "gray and white two-legged juvenile" msgid_plural "gray and white two-legged juveniles" -msgstr[0] "" +msgstr[0] "灰白色双足恐龙幼仔" #: data/mods/DinoMod/monsters/juvenile.json msgid "" @@ -182369,7 +182634,7 @@ msgstr "一只四足食草蜥脚恐龙幼仔,脖子很长。" #: data/mods/DinoMod/monsters/juvenile.json msgid "brown and magenta sauropod juvenile" msgid_plural "brown and magenta sauropod juveniles" -msgstr[0] "" +msgstr[0] "棕紫色蜥脚类恐龙幼仔" #. ~ Description for brown and magenta sauropod juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -182381,7 +182646,7 @@ msgstr "一只巨型四足食草蜥脚类恐龙幼仔,有着长长的脖子和 #: data/mods/DinoMod/monsters/juvenile.json msgid "green and magenta four-legged juvenile" msgid_plural "green and magenta four-legged juveniles" -msgstr[0] "" +msgstr[0] "绿紫色四足恐龙幼仔" #. ~ Description for green and magenta four-legged juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -182393,7 +182658,7 @@ msgstr "一只小型四足食草恐龙幼仔,太小了以至于你无法分辨 #: data/mods/DinoMod/monsters/juvenile.json msgid "green and yellow four-legged juvenile" msgid_plural "green and yellow four-legged juveniles" -msgstr[0] "" +msgstr[0] "绿黄色四足恐龙幼仔" #: data/mods/DinoMod/monsters/juvenile.json msgid "gray and magenta two-legged juvenile" @@ -182518,7 +182783,7 @@ msgstr "一只双足食草恐龙幼仔,长着粗壮的前肢和多齿的长喙 #: data/mods/DinoMod/monsters/juvenile.json msgid "winged juvenile" msgid_plural "winged juveniles" -msgstr[0] "" +msgstr[0] "长翼恐龙幼仔" #. ~ Description for winged juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -182530,7 +182795,7 @@ msgstr "一只小型长翼恐龙幼仔,长着大而闪亮的眼睛,太小了 #: data/mods/DinoMod/monsters/juvenile.json msgid "mosasaurus juvenile" msgid_plural "mosasaurus juveniles" -msgstr[0] "" +msgstr[0] "沧龙幼仔" #. ~ Description for mosasaurus juvenile #: data/mods/DinoMod/monsters/juvenile.json @@ -182706,7 +182971,7 @@ msgstr "一具巨大的蹒跚而行的恐龙尸体,撑起了巨大的大嘴, #: data/mods/DinoMod/monsters/zed-dinosaur.json msgid "Z-Rex" msgid_plural "Z-Rexes" -msgstr[0] "" +msgstr[0] "丧尸霸王龙" #. ~ Description for {'str': 'Z-Rex', 'str_pl': 'Z-Rexes'} #: data/mods/DinoMod/monsters/zed-dinosaur.json @@ -183260,7 +183525,7 @@ msgstr "一具体表覆盖着破碎羽毛和黑色腐臭液体的蹒跚而行的 #: data/mods/DinoMod/monsters/zed-dinosaur.json msgid "chained Pachycephalosaurus zombie" msgid_plural "chained Pachycephalosaurus zombies" -msgstr[0] "" +msgstr[0] "被拴住的丧尸厚头龙" #. ~ Description for {'str': 'chained Pachycephalosaurus zombie'} #: data/mods/DinoMod/monsters/zed-dinosaur.json @@ -183472,7 +183737,7 @@ msgstr "一副破烂肿胀的巨型水生恐龙尸体,一栋小房子大小, #: data/mods/DinoMod/monsters/zed-dinosaur.json msgid "juvenile sauropod zombie" msgid_plural "juvenile sauropod zombies" -msgstr[0] "" +msgstr[0] "丧尸蜥脚类幼龙" #. ~ Description for {'str': 'juvenile sauropod zombie'} #: data/mods/DinoMod/monsters/zed-dinosaur.json @@ -183491,7 +183756,7 @@ msgstr "一具食草四足恐龙幼仔尸体,长着开裂的天然骨甲。" #: data/mods/DinoMod/monsters/zed-dinosaur_CBM.json msgid "Spinosaurus zombie bio-operator" msgid_plural "Spinosaurus zombie bio-operators" -msgstr[0] "" +msgstr[0] "丧尸生化棘龙" #. ~ Description for {'str': 'Spinosaurus zombie bio-operator'} #: data/mods/DinoMod/monsters/zed-dinosaur_CBM.json @@ -183504,7 +183769,7 @@ msgstr "一具闪光的带鳍兽脚类恐龙尸体,浑身布满了带血盔甲 #: data/mods/DinoMod/monsters/zed-dinosaur_CBM.json msgid "Gallimimus zombie bio-operator" msgid_plural "Gallimimus zombie bio-operators" -msgstr[0] "" +msgstr[0] "丧尸生化似鸡龙" #. ~ Description for {'str': 'Gallimimus zombie bio-operator'} #: data/mods/DinoMod/monsters/zed-dinosaur_CBM.json @@ -184297,7 +184562,7 @@ msgstr "一头严重烧伤的丧尸水生恐龙,烧焦的血肉散发着恶臭 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Crested Crusher" msgid_plural "Crested Crushers" -msgstr[0] "" +msgstr[0] "恐怖双脊龙" #. ~ Description for {'str': 'Crested Crusher'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184312,7 +184577,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Draco Titan" msgid_plural "Draco Titans" -msgstr[0] "" +msgstr[0] "恐怖角鼻龙" #. ~ Description for {'str': 'Draco Titan'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184326,7 +184591,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Spino Sledge" msgid_plural "Spino Sledges" -msgstr[0] "" +msgstr[0] "恐怖棘龙" #. ~ Description for {'str': 'Spino Sledge'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184353,7 +184618,7 @@ msgstr "一具巨大的腐烂恐龙尸体,长着长而锋利的牙齿,眼睛 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Allosaurus Avalanche" msgid_plural "Allosaurus Avalanches" -msgstr[0] "" +msgstr[0] "恐怖异特龙" #. ~ Description for {'str': 'Allosaurus Avalanche'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184365,7 +184630,7 @@ msgstr "一具巨大的蹒跚而行的双足食肉恐龙尸体,宽阔的脊背 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Acrocanthosaurus Avenger" msgid_plural "Acrocanthosaurus Avengers" -msgstr[0] "" +msgstr[0] "恐怖高棘龙" #. ~ Description for {'str': 'Acrocanthosaurus Avenger'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184378,7 +184643,7 @@ msgstr "一具巨大的蹒跚而行的双足食肉恐龙尸体,长着锯齿状 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Siats Stonehenge" msgid_plural "Siats Stonehenges" -msgstr[0] "" +msgstr[0] "恐怖西雅茨龙" #. ~ Description for {'str': 'Siats Stonehenge'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184421,7 +184686,7 @@ msgstr[0] "恐怖戈尔冈龙" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Alberta Anvil" msgid_plural "Alberta Anvils" -msgstr[0] "" +msgstr[0] "恐怖阿尔伯塔龙" #. ~ Description for {'str': 'Alberta Anvil'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184433,7 +184698,7 @@ msgstr "一具巨大的恐龙尸体撑起了巨大的大嘴和一对贪婪的利 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Qianzhousaurus chéngqiáng" msgid_plural "Qianzhousaurus chéngqiángs" -msgstr[0] "" +msgstr[0] "恐怖虔州龙" #. ~ Description for {'str': 'Qianzhousaurus chéngqiáng'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184475,7 +184740,7 @@ msgstr "一大坨破烂发臭的血肉,托起了它巨大的牙齿。它的整 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Gruesome Gallimimus" msgid_plural "Gruesome Gallimimus" -msgstr[0] "" +msgstr[0] "恐怖似鸡龙" #. ~ Description for {'str_sp': 'Gruesome Gallimimus'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184527,7 +184792,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Deino Destroyer" msgid_plural "Deino Destroyers" -msgstr[0] "" +msgstr[0] "恐怖恐爪龙" #. ~ Description for {'str': 'Deino Destroyer'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184542,7 +184807,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Utah Hoodoo" msgid_plural "Utah Hoodoos" -msgstr[0] "" +msgstr[0] "恐怖犹他盗龙" #. ~ Description for {'str': 'Utah Hoodoo'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184605,7 +184870,7 @@ msgstr "一具巨大的长颈四足恐龙尸体,尾巴非常长。它的整个 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Spiked Dreadnaught" msgid_plural "Spiked Dreadnaughts" -msgstr[0] "" +msgstr[0] "恐怖阿马加龙" #. ~ Description for {'str': 'Spiked Dreadnaught'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184633,12 +184898,12 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Brontosaurus Brute" msgid_plural "Brontosaurus Brutes" -msgstr[0] "" +msgstr[0] "恐怖雷龙" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Flail Fiend" msgid_plural "Flail Fiends" -msgstr[0] "" +msgstr[0] "恐怖梁龙" #. ~ Description for {'str': 'Flail Fiend'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184666,7 +184931,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Zombie Freight Train" msgid_plural "Zombie Freight Trains" -msgstr[0] "" +msgstr[0] "恐怖圆头龙" #. ~ Description for {'str': 'Zombie Freight Train'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184679,7 +184944,7 @@ msgstr "一具巨大的蹒跚而行的四足恐龙尸体,长着方形的头和 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Brachiosaurus Brute" msgid_plural "Brachiosaurus Brutes" -msgstr[0] "" +msgstr[0] "恐怖腕龙" #. ~ Description for {'str': 'Brachiosaurus Brute'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184705,7 +184970,7 @@ msgstr "一具巨大的蹒跚而行的长颈四足恐龙尸体,脖子很长, #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Stegosaurus Sledge" msgid_plural "Stegosaurus Sledges" -msgstr[0] "" +msgstr[0] "恐怖剑龙" #. ~ Description for {'str': 'Stegosaurus Sledge'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184769,7 +185034,7 @@ msgstr "这具四足恐龙丧尸装备着厚重盔甲,两边有着巨大骨刺 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Nodosaurus Neutralizer" msgid_plural "Nodosaurus Neutralizers" -msgstr[0] "" +msgstr[0] "恐怖结节龙" #. ~ Description for {'str': 'Nodosaurus Neutralizer'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184796,7 +185061,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Edmontonia Elbow" msgid_plural "Edmontonia Elbows" -msgstr[0] "" +msgstr[0] "恐怖埃德蒙顿甲龙" #. ~ Description for {'str': 'Edmontonia Elbow'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184821,7 +185086,7 @@ msgstr "这具四足恐龙丧尸装备着厚重盔甲,全身布满尖刺并有 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Dino Tankette" msgid_plural "Dino Tankettes" -msgstr[0] "" +msgstr[0] "恐怖倍甲龙" #. ~ Description for {'str': 'Dino Tankette'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184833,7 +185098,7 @@ msgstr "这具巨大的恐龙尸体看上去像是一种巨大的史前犰狳, #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Dino Tank" msgid_plural "Dino Tanks" -msgstr[0] "" +msgstr[0] "恐怖甲龙" #. ~ Description for {'str': 'Dino Tank'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184900,7 +185165,7 @@ msgstr "这具拖着脚步的羽毛恐龙尸体是一种双足恐龙,具有异 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Crusher Camp" msgid_plural "Crusher Camps" -msgstr[0] "" +msgstr[0] "恐怖弯龙" #. ~ Description for {'str': 'Crusher Camp'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184926,7 +185191,7 @@ msgstr "一具巨大的、蹒跚而行的四足恐龙尸体,长着长喙。它 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Mother Crusher" msgid_plural "Mother Crushers" -msgstr[0] "" +msgstr[0] "恐怖慈母龙" #. ~ Description for {'str': 'Mother Crusher'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184979,7 +185244,7 @@ msgstr "一只巨大的有鳞恐龙,有蹄,宽阔的喙嘴和多刺的头冠 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Edmonton Everest" msgid_plural "Edmonton Everests" -msgstr[0] "" +msgstr[0] "恐怖埃德蒙顿龙" #. ~ Description for {'str': 'Edmonton Everest'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -184993,7 +185258,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Parasaur Punch" msgid_plural "Parasaur Punches" -msgstr[0] "" +msgstr[0] "恐怖副栉龙" #. ~ Description for {'str': 'Parasaur Punch', 'str_pl': 'Parasaur Punches'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185020,7 +185285,7 @@ msgstr "一只巨大的有鳞恐龙,短喙和形状像斧头的头冠,已经 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Cory Crusher" msgid_plural "Cory Crushers" -msgstr[0] "" +msgstr[0] "恐怖冠龙" #. ~ Description for {'str': 'Cory Crusher'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185047,7 +185312,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Skull Breaker" msgid_plural "Skull Breakers" -msgstr[0] "" +msgstr[0] "恐怖厚头龙" #. ~ Description for {'str': 'Skull Breaker'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185138,7 +185403,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Dino Rhino" msgid_plural "Dino Rhinos" -msgstr[0] "" +msgstr[0] "恐怖厚鼻龙" #. ~ Description for {'str': 'Dino Rhino'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185181,7 +185446,7 @@ msgstr "" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Kosmic Horror" msgid_plural "Kosmic Horrors" -msgstr[0] "" +msgstr[0] "恐怖科斯莫角龙" #. ~ Description for {'str': 'Kosmic Horror'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185194,7 +185459,7 @@ msgstr "一具体型巨大的犀牛一般的蹒跚而行的恐龙尸体。头上 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Bull Dino" msgid_plural "Bull Dinos" -msgstr[0] "" +msgstr[0] "恐怖牛角龙" #. ~ Description for {'str': 'Bull Dino'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185207,7 +185472,7 @@ msgstr "一具体型巨大的犀牛一般的蹒跚而行的恐龙尸体。头上 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Triceratruck" msgid_plural "Triceratrucks" -msgstr[0] "" +msgstr[0] "恐怖三角龙" #. ~ Description for {'str': 'Triceratruck'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185236,7 +185501,7 @@ msgstr "一具体表覆盖着破碎羽毛和黑色腐臭液体的蹒跚而行的 #: data/mods/DinoMod/obsolete/monsters.json msgid "Winged Horror" msgid_plural "Winged Horrors" -msgstr[0] "" +msgstr[0] "恐怖双型齿翼龙" #. ~ Description for {'str': 'Winged Horror'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -185922,7 +186187,7 @@ msgstr[0] "骸骨惧龙" #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "S-Rex" msgid_plural "S-Rexes" -msgstr[0] "" +msgstr[0] "骸骨霸王龙" #. ~ Description for {'str': 'S-Rex', 'str_pl': 'S-Rexes'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -186622,7 +186887,7 @@ msgstr "一只巨大的丧尸蜥脚类恐龙举起了一架看起来像是坠毁 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Tankylosaurus" msgid_plural "Tankylosaurus" -msgstr[0] "" +msgstr[0] "坦克甲龙" #. ~ Description for {'str_sp': 'Tankylosaurus'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -186686,7 +186951,7 @@ msgstr "一具因为丧尸化而严重肿胀的比正常更加高耸入云的蜥 #: data/mods/DinoMod/monsters/zinosaur_upgrade.json msgid "Ankylosaurus hulk" msgid_plural "Ankylosaurus hulk" -msgstr[0] "" +msgstr[0] "浩克丧尸甲龙" #. ~ Description for {'str_sp': 'Ankylosaurus hulk'} #: data/mods/DinoMod/monsters/zinosaur_upgrade.json @@ -187149,7 +187414,7 @@ msgstr "野生動物飼養基地" #: data/mods/DinoMod/obsolete/monsters.json msgid "Dimorphodon zombie" msgid_plural "Dimorphodon zombie" -msgstr[0] "" +msgstr[0] "丧尸双型齿翼龙" #. ~ Description for {'str_sp': 'Dimorphodon zombie'} #: data/mods/DinoMod/obsolete/monsters.json @@ -187169,7 +187434,7 @@ msgstr "一具长着破碎羽毛的蹒跚而行的爬行动物尸体,有三英 #: data/mods/DinoMod/obsolete/monsters.json msgid "Dimorphozombie bio-operator" msgid_plural "Dimorphozombie bio-operators" -msgstr[0] "" +msgstr[0] "丧尸生化双型齿翼龙" #. ~ Description for {'str': 'Dimorphozombie bio-operator'} #: data/mods/DinoMod/obsolete/monsters.json @@ -188186,7 +188451,7 @@ msgstr "一套用於玩 \"巫術\" 遊戲的卡片。每張卡片都有不同怪 #: data/mods/Fuji_Structures/items/items_games.json msgid "Picturesque" msgid_plural "sets of Picturesque" -msgstr[0] "" +msgstr[0] "我画你猜" #. ~ Description for {'str': 'Picturesque', 'str_pl': 'sets of Picturesque'} #: data/mods/Fuji_Structures/items/items_games.json @@ -188197,7 +188462,7 @@ msgstr "一個人畫圖, 其他人猜他畫什麼的遊戲。" #: data/mods/Fuji_Structures/items/items_games.json msgid "Capitalism" msgid_plural "sets of Capitalism" -msgstr[0] "" +msgstr[0] "大富翁" #. ~ Description for {'str': 'Capitalism', 'str_pl': 'sets of Capitalism'} #: data/mods/Fuji_Structures/items/items_games.json @@ -188209,7 +188474,7 @@ msgstr "一套桌遊, 玩家們在遊戲盤上遊轉、購買房產, 和訛詐 #: data/mods/Fuji_Structures/items/items_games.json msgid "Blobs and Bandits" msgid_plural "sets of Blobs and Bandits" -msgstr[0] "" +msgstr[0] "变形怪和强盗们" #. ~ Description for {'str': 'Blobs and Bandits', 'str_pl': 'sets of Blobs and #. Bandits'} @@ -188222,7 +188487,7 @@ msgstr "一套桌上角色扮演遊戲, 設定在大災變之後, 讓你模擬 #: data/mods/Fuji_Structures/items/items_games.json msgid "Battlehammer" msgid_plural "sets of Battlehammer" -msgstr[0] "" +msgstr[0] "战锤" #. ~ Description for {'str': 'Battlehammer', 'str_pl': 'sets of Battlehammer'} #: data/mods/Fuji_Structures/items/items_games.json @@ -188233,7 +188498,7 @@ msgstr "一款桌上戰棋遊戲, 內含一組奇幻生物的小小公仔。" #: data/mods/Fuji_Structures/items/items_games.json msgid "Battlehammer 20k" msgid_plural "sets of Battlehammer 20k" -msgstr[0] "" +msgstr[0] "战锤20K" #. ~ Description for {'str': 'Battlehammer 20k', 'str_pl': 'sets of #. Battlehammer 20k'} @@ -188246,7 +188511,7 @@ msgstr "一款桌上戰棋遊戲, 內含一組外星人和異空間海軍陸戰 #: data/mods/Fuji_Structures/items/items_games.json msgid "Settlers of the Ranch" msgid_plural "sets of Settlers of the Ranch" -msgstr[0] "" +msgstr[0] "农场大亨" #. ~ Description for {'str': 'Settlers of the Ranch', 'str_pl': 'sets of #. Settlers of the Ranch'} @@ -188258,7 +188523,7 @@ msgstr "一個戰略遊戲, 讓玩家們各自建造拓荒營地並交易各種 #: data/mods/Fuji_Structures/items/items_games.json msgid "Warships" msgid_plural "sets of Warships" -msgstr[0] "" +msgstr[0] "战舰" #. ~ Description for {'str': 'Warships', 'str_pl': 'sets of Warships'} #: data/mods/Fuji_Structures/items/items_games.json @@ -188270,7 +188535,7 @@ msgstr "玩家互猜對手將軍艦放在棋盤上位置的遊戲。" #: data/mods/Fuji_Structures/items/items_games.json msgid "Murder Mystery" msgid_plural "sets of Murder Mystery" -msgstr[0] "" +msgstr[0] "神秘谋杀案" #. ~ Description for {'str': 'Murder Mystery', 'str_pl': 'sets of Murder #. Mystery'} @@ -188601,7 +188866,7 @@ msgstr "" #: data/mods/Generic_Guns/ammo/casings.json msgid "shotshell hull" msgid_plural "shotshell hulls" -msgstr[0] "" +msgstr[0] "霰弹弹壳" #. ~ Description for shotshell hull #: data/mods/Generic_Guns/ammo/casings.json @@ -188722,53 +188987,53 @@ msgstr "一颗独头榴弹,里面装着一颗巨大的弹头。我想跟你的 #: data/mods/Generic_Guns/ammo/obsolete.json msgid "pistol ammo, ball (reloaded)" msgid_plural "pistol ammo, ball (reloaded)" -msgstr[0] "" +msgstr[0] "手枪球形弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "pistol ammo, JHP (reloaded)" msgid_plural "pistol ammo, JHP (reloaded)" -msgstr[0] "" +msgstr[0] "手枪空尖弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "tiny pistol ammo, ball (reloaded)" msgid_plural "tiny pistol ammo, ball (reloaded)" -msgstr[0] "" +msgstr[0] "小型手枪球形弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "tiny pistol ammo, JHP (reloaded)" msgid_plural "tiny pistol ammo, JHP (reloaded)" -msgstr[0] "" +msgstr[0] "小型手枪空尖弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "magnum ammo, ball (reloaded)" msgid_plural "magnum ammo, ball (reloaded)" -msgstr[0] "" +msgstr[0] "马格南球形弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "magnum ammo, JHP (reloaded)" msgid_plural "magnum ammo, JHP (reloaded)" -msgstr[0] "" +msgstr[0] "马格南空尖弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, buckshot (reloaded)" msgid_plural "shotshell, buckshot (reloaded)" -msgstr[0] "" +msgstr[0] "猎鹿霰弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, birdshot (reloaded)" msgid_plural "shotshell, birdshot (reloaded)" -msgstr[0] "" +msgstr[0] "猎鸟霰弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, slug (reloaded)" msgid_plural "shotshell, slug (reloaded)" -msgstr[0] "" +msgstr[0] "独头霰弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, junk" msgid_plural "shotshell, junk" -msgstr[0] "" +msgstr[0] "废品霰弹" #: data/mods/Generic_Guns/ammo/obsolete.json #: data/mods/Generic_Guns/ammo/shot.json @@ -188790,12 +189055,12 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "shotshell, pyrotechnical (reloaded)" msgid_plural "shotshell, pyrotechnical (reloaded)" -msgstr[0] "" +msgstr[0] "烟火霰弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, AP" msgid_plural "rifle ammo, AP" -msgstr[0] "" +msgstr[0] "步枪穿甲弹" #. ~ Description for {'str_sp': 'rifle ammo, AP'} #: data/mods/Generic_Guns/ammo/obsolete.json @@ -188811,22 +189076,22 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, ball (reloaded)" msgid_plural "rifle ammo, ball (reloaded)" -msgstr[0] "" +msgstr[0] "步枪球形弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, AP (reloaded)" msgid_plural "rifle ammo, AP (reloaded)" -msgstr[0] "" +msgstr[0] "步枪穿甲弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "rifle ammo, AP (black powder)" msgid_plural "rifle ammo, AP (black powder)" -msgstr[0] "" +msgstr[0] "步枪穿甲弹(黑火药)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "huge rifle ammo, AP" msgid_plural "huge rifle ammo, AP" -msgstr[0] "" +msgstr[0] "大型步枪穿甲弹" #. ~ Description for {'str_sp': 'huge rifle ammo, AP'} #: data/mods/Generic_Guns/ammo/obsolete.json @@ -188841,12 +189106,12 @@ msgstr "" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "huge rifle ammo, ball (reloaded)" msgid_plural "huge rifle ammo, ball (reloaded)" -msgstr[0] "" +msgstr[0] "大型步枪球形弹(复装)" #: data/mods/Generic_Guns/ammo/obsolete.json msgid "huge rifle ammo, AP (reloaded)" msgid_plural "huge rifle ammo, AP (reloaded)" -msgstr[0] "" +msgstr[0] "大型步枪穿甲弹(复装)" #: data/mods/Generic_Guns/ammo/pistol.json msgid "9mm, FMJ" @@ -189143,7 +189408,7 @@ msgstr[0] "" #: data/mods/Generic_Guns/ammo/rocket.json msgid "rocket, antipersonnel" msgid_plural "rocket, antipersonnel" -msgstr[0] "" +msgstr[0] "反步兵火箭弹" #. ~ Description for {'str_sp': 'rocket, antipersonnel'} #: data/mods/Generic_Guns/ammo/rocket.json @@ -189155,7 +189420,7 @@ msgstr "一个用于军用火箭发射器的大型反步兵火箭弹。设计成 #: data/mods/Generic_Guns/ammo/rocket.json msgid "rocket, multipurpose" msgid_plural "rocket, multipurpose" -msgstr[0] "" +msgstr[0] "多用途火箭弹" #. ~ Description for {'str_sp': 'rocket, multipurpose'} #: data/mods/Generic_Guns/ammo/rocket.json @@ -189168,7 +189433,7 @@ msgstr "一种反坦克火箭弹,带有高爆两用弹头,供军用火箭发 #: data/mods/Generic_Guns/ammo/rocket.json msgid "rocket, smoke" msgid_plural "rocket, smoke" -msgstr[0] "" +msgstr[0] "烟雾火箭弹" #. ~ Description for {'str_sp': 'rocket, smoke'} #: data/mods/Generic_Guns/ammo/rocket.json @@ -189181,17 +189446,17 @@ msgstr "一个装有烟雾弹头的火箭弹,供军用火箭发射器使用。 #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, buckshot" msgid_plural "shotshell, buckshot" -msgstr[0] "" +msgstr[0] "猎鹿霰弹" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, beanbag" msgid_plural "shotshell, beanbag" -msgstr[0] "" +msgstr[0] "沙包霰弹" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, birdshot" msgid_plural "shotshell, birdshot" -msgstr[0] "" +msgstr[0] "猎鸟霰弹" #. ~ Description for {'str_sp': 'shotshell, birdshot'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189203,7 +189468,7 @@ msgstr "装满了无数细小弹丸的霰弹枪弹药。用来狩猎鸟类和其 #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, slug" msgid_plural "shotshell, slug" -msgstr[0] "" +msgstr[0] "独头霰弹" #. ~ Description for {'str_sp': 'shotshell, slug'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189216,7 +189481,7 @@ msgstr "装着单一弹头的霰弹,弹头形状有点像羽毛球。独头霰 #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, pyrotechnical" msgid_plural "shotshell, pyrotechnical" -msgstr[0] "" +msgstr[0] "烟火霰弹" #. ~ Description for {'str_sp': 'shotshell, pyrotechnical'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189230,7 +189495,7 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, buckshot (black powder)" msgid_plural "shotshell, buckshot (black powder)" -msgstr[0] "" +msgstr[0] "猎鹿霰弹(黑火药)" #. ~ Description for {'str_sp': 'shotshell, buckshot (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189243,7 +189508,7 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, birdshot (black powder)" msgid_plural "shotshell, birdshot (black powder)" -msgstr[0] "" +msgstr[0] "猎鸟霰弹(黑火药)" #. ~ Description for {'str_sp': 'shotshell, birdshot (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189256,7 +189521,7 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, slug (black powder)" msgid_plural "shotshell, slug (black powder)" -msgstr[0] "" +msgstr[0] "独头霰弹(黑火药)" #. ~ Description for {'str_sp': 'shotshell, slug (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189271,7 +189536,7 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, pyrotechnical (black powder)" msgid_plural "shotshell, pyrotechnical (black powder)" -msgstr[0] "" +msgstr[0] "烟火霰弹(黑火药)" #. ~ Description for {'str_sp': 'shotshell, pyrotechnical (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189285,7 +189550,7 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, flechette (black powder)" msgid_plural "shotshell, flechette (black powder)" -msgstr[0] "" +msgstr[0] "镖形霰弹(黑火药)" #. ~ Description for {'str_sp': 'shotshell, flechette (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189299,7 +189564,7 @@ msgstr "" #: data/mods/Generic_Guns/ammo/shot.json msgid "shotshell, junk (black powder)" msgid_plural "shotshell, junk (black powder)" -msgstr[0] "" +msgstr[0] "废品霰弹(黑火药)" #. ~ Description for {'str_sp': 'shotshell, junk (black powder)'} #: data/mods/Generic_Guns/ammo/shot.json @@ -189369,7 +189634,7 @@ msgstr "" #: data/mods/Generic_Guns/firearms/black_powder.json msgid "antique pistol" msgid_plural "antique pistols" -msgstr[0] "" +msgstr[0] "古董手枪" #: data/mods/Generic_Guns/firearms/black_powder.json msgid "" @@ -189383,7 +189648,7 @@ msgstr "" #: data/mods/Generic_Guns/firearms/black_powder.json msgid "antique revolver" msgid_plural "antique revolvers" -msgstr[0] "" +msgstr[0] "古董左轮" #: data/mods/Generic_Guns/firearms/black_powder.json msgid "" @@ -189397,7 +189662,7 @@ msgstr "" #: data/mods/Generic_Guns/firearms/black_powder.json msgid "antique musket" msgid_plural "antique muskets" -msgstr[0] "" +msgstr[0] "古董火枪" #: data/mods/Generic_Guns/firearms/black_powder.json msgid "" @@ -189829,7 +190094,7 @@ msgstr "" #: data/mods/Generic_Guns/firearms/rocket.json msgid "disposable rocket launcher" msgid_plural "disposable rocket launchers" -msgstr[0] "" +msgstr[0] "一次性火箭发射器" #: data/mods/Generic_Guns/firearms/rocket.json msgid "" @@ -189862,7 +190127,7 @@ msgstr "" #: data/mods/Generic_Guns/firearms/shot.json msgid "double-barrel shotgun" msgid_plural "double-barrel shotguns" -msgstr[0] "" +msgstr[0] "双管霰弹枪" #: data/mods/Generic_Guns/firearms/shot.json msgid "" @@ -189937,7 +190202,7 @@ msgstr "" #: data/mods/Generic_Guns/firearms/sniper.json msgid "sniper rifle" msgid_plural "sniper rifles" -msgstr[0] "" +msgstr[0] "狙击步枪" #: data/mods/Generic_Guns/gunmods/gunmods.json msgid "40mm underbarrel grenade launcher" @@ -189975,12 +190240,12 @@ msgstr "" #: data/mods/Generic_Guns/gunmods/gunmods.json msgid "underbarrel shotgun" msgid_plural "underbarrel shotguns" -msgstr[0] "" +msgstr[0] "管下霰弹枪" #: data/mods/Generic_Guns/gunmods/gunmods.json msgid "modified underbarrel shotgun" msgid_plural "modified underbarrel shotguns" -msgstr[0] "" +msgstr[0] "管下霰弹枪(改)" #: data/mods/Generic_Guns/magazines/grenade.json msgid "40mm grenade belt" @@ -190190,7 +190455,7 @@ msgstr "" #: data/mods/Generic_Guns/magazines/shot.json msgid "shotgun box magazine" msgid_plural "shotgun box magazines" -msgstr[0] "" +msgstr[0] "霰弹枪盒式弹匣" #. ~ Description for shotgun box magazine #: data/mods/Generic_Guns/magazines/shot.json @@ -190216,7 +190481,7 @@ msgstr "" #: data/mods/Generic_Guns/magazines/shot.json msgid "shotgun speedloader" msgid_plural "shotgun speedloaders" -msgstr[0] "" +msgstr[0] "霰弹快速装弹器" #. ~ Description for shotgun speedloader #: data/mods/Generic_Guns/magazines/shot.json @@ -190269,13 +190534,13 @@ msgstr "" #: data/mods/Generic_Guns/robots/active_bots.json msgid "improvised SMG turret" msgid_plural "improvised SMG turrets" -msgstr[0] "" +msgstr[0] "自制冲锋枪炮塔" #: data/mods/Generic_Guns/robots/active_bots.json #: data/mods/Generic_Guns/robots/inactive_bots.json msgid "CROWS II, heavy machinegun" msgid_plural "CROWS II, heavy machineguns" -msgstr[0] "" +msgstr[0] "CROWS II 重机枪炮塔" #. ~ Description for {'str': 'CROWS II, heavy machinegun'} #: data/mods/Generic_Guns/robots/active_bots.json @@ -190292,7 +190557,7 @@ msgstr "" #: data/mods/Generic_Guns/robots/active_bots.json msgid "CROWS II, light machinegun" msgid_plural "CROWS II, light machineguns" -msgstr[0] "" +msgstr[0] "CROWS II 轻机枪炮塔" #. ~ Description for {'str': 'CROWS II, light machinegun'} #: data/mods/Generic_Guns/robots/active_bots.json @@ -190309,7 +190574,7 @@ msgstr "" #: data/mods/Generic_Guns/robots/active_bots.json msgid "autonomous rifle TALON UGV" msgid_plural "autonomous rifle TALON UGVs" -msgstr[0] "" +msgstr[0] "步枪型 \"鹰爪\" 无人车" #. ~ Description for {'str': 'autonomous rifle TALON UGV'} #: data/mods/Generic_Guns/robots/active_bots.json @@ -190322,7 +190587,7 @@ msgstr "一架\"鹰爪\"型无人车,配有一把标准突击步枪。这是 #: data/mods/Generic_Guns/robots/active_bots.json msgid "autonomous launcher TALON UGV" msgid_plural "autonomous launcher TALON UGVs" -msgstr[0] "" +msgstr[0] "发射器型 \"鹰爪\" 无人车" #. ~ Description for {'str': 'autonomous launcher TALON UGV'} #: data/mods/Generic_Guns/robots/active_bots.json @@ -190335,22 +190600,22 @@ msgstr "一架\"鹰爪\"型无人车,配有一台多管榴弹发射器。这 #: data/mods/Generic_Guns/robots/broken_bots.json msgid "broken CROWS II" msgid_plural "broken CROWS IIs" -msgstr[0] "" +msgstr[0] "CROWS II 炮塔(损坏)" #: data/mods/Generic_Guns/robots/broken_bots.json msgid "broken CROWS II Heavy" msgid_plural "broken CROWS II Heavys" -msgstr[0] "" +msgstr[0] "CROWS II 重型炮塔(损坏)" #: data/mods/Generic_Guns/robots/broken_bots.json msgid "broken launcher TALON UGV" msgid_plural "broken launcher TALON UGVs" -msgstr[0] "" +msgstr[0] "发射器型 \"鹰爪\" 无人车(损坏)" #: data/mods/Generic_Guns/robots/broken_bots.json msgid "broken rifle TALON UGV" msgid_plural "broken rifle TALON UGVs" -msgstr[0] "" +msgstr[0] "步枪型 \"鹰爪\" 无人车(损坏)" #. ~ Description for {'str': 'longrange milspec turret'} #: data/mods/Generic_Guns/robots/gg_bots_migration.json @@ -190379,7 +190644,7 @@ msgstr "" #: data/mods/Generic_Guns/robots/inactive_bots.json msgid "inactive CROWS II, light machinegun" msgid_plural "inactive CROWS II, light machineguns" -msgstr[0] "" +msgstr[0] "CROWS II 轻机枪炮塔(关)" #. ~ Description for {'str': 'inactive CROWS II, light machinegun'} #: data/mods/Generic_Guns/robots/inactive_bots.json @@ -190421,7 +190686,7 @@ msgstr "" #: data/mods/Generic_Guns/robots/inactive_bots.json msgid "inactive launcher TALON UGV" msgid_plural "inactive launcher TALON UGVs" -msgstr[0] "" +msgstr[0] "发射器型 \"鹰爪\" 无人车(关)" #. ~ Description for {'str': 'inactive launcher TALON UGV'} #: data/mods/Generic_Guns/robots/inactive_bots.json @@ -190459,42 +190724,42 @@ msgstr "车载自动榴弹发射器" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "HK417 magazine" msgid_plural "HK417 magazines" -msgstr[0] "" +msgstr[0] "HK417 步枪弹匣" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "HK417 compact magazine" msgid_plural "HK417 compact magazines" -msgstr[0] "" +msgstr[0] "HK417 紧凑型步枪弹匣" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "HK417 makeshift magazine" msgid_plural "HK417 makeshift magazines" -msgstr[0] "" +msgstr[0] "自制 HK417 步枪弹匣" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "Ruger .223 5-round magazine" msgid_plural "Ruger .223 5-round magazines" -msgstr[0] "" +msgstr[0] "鲁格 .223 5发弹匣" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "Ruger .223 10-round magazine" msgid_plural "Ruger .223 10-round magazines" -msgstr[0] "" +msgstr[0] "鲁格 .223 10发弹匣" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "Ruger .223 high-capacity magazine" msgid_plural "Ruger .223 high-capacity magazines" -msgstr[0] "" +msgstr[0] "鲁格 .233 大容量弹匣" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "STANAG magazine" msgid_plural "STANAG magazines" -msgstr[0] "" +msgstr[0] "STANAG 北约制式弹匣" #: data/mods/Generic_Guns/vehicles/ammo_redefine_hacks/temp_magazine_json_load_hack.json msgid "STANAG drum magazine" msgid_plural "STANAG drum magazines" -msgstr[0] "" +msgstr[0] "STANAG 北约制式弹鼓" #: data/mods/Graphical_Overmap/modinfo.json msgid "Larwick's Overmap" @@ -190546,7 +190811,7 @@ msgstr "极大地限制了真菌的指数增长能力。" #: data/mods/MMA/martial.json msgid "The Life and Work of Tiger Sauer" msgid_plural "The Life and Work of Tiger Sauer" -msgstr[0] "" +msgstr[0] "泰格·斯奥尔的生活和工作" #. ~ Description for {'str_sp': 'The Life and Work of Tiger Sauer'} #: data/mods/MMA/martial.json @@ -190846,7 +191111,7 @@ msgstr "一个大型石头祭坛。最常用于各类不合伦理的仪式。" #: data/mods/Magiclysm/furniture.json data/mods/Magiclysm/items/tools.json msgid "demon forge" msgid_plural "demon forges" -msgstr[0] "" +msgstr[0] "恶魔熔炉" #. ~ Description for demon forge #: data/mods/Magiclysm/furniture.json @@ -191234,6 +191499,11 @@ msgstr "藥劑" msgid "RUNES" msgstr "符文" +#. ~ Crafting recipes subcategory of 'ENCHANTED' category +#: data/mods/Magiclysm/qualities.json +msgid "ENCHANTING" +msgstr "" + #: data/mods/Magiclysm/qualities.json msgid "mana focusing" msgstr "法力聚焦" @@ -191367,6 +191637,21 @@ msgctxt "start_name" msgid "Wizard's Retreat Vacation" msgstr "魔法师度假地" +#: data/mods/Magiclysm/species.json +msgid "magical beast" +msgid_plural "magical beasts" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "dragon" +msgid_plural "dragons" +msgstr[0] "" + +#: data/mods/Magiclysm/species.json +msgid "lizardfolk" +msgid_plural "lizardfolk" +msgstr[0] "" + #: data/mods/Magiclysm/start_locations.json msgid "Wizard's Secret Basement Study" msgstr "魔法師的秘密地下研究室" @@ -193613,7 +193898,7 @@ msgstr "这个手镯上刻着符文。当你看着它的时候,你会感觉到 #: data/mods/Magiclysm/items/alchemy_items.json msgid "silver infusion bracelet" msgid_plural "silver infusion bracelets" -msgstr[0] "" +msgstr[0] "符文银手镯" #: data/mods/Magiclysm/items/alchemy_items.json msgid "copper circlet" @@ -193642,7 +193927,7 @@ msgstr "一支短石鑿。它可用於雕刻石材、木材或軟質金屬。" #: data/mods/Magiclysm/items/alchemy_items.json msgid "potion starter" msgid_plural "potion starters" -msgstr[0] "" +msgstr[0] "基础药剂" #. ~ Description for potion starter #: data/mods/Magiclysm/items/alchemy_items.json @@ -193654,7 +193939,7 @@ msgstr "強烈的酒精,注入法力並濃縮成液體,可以使法術穩定 #: data/mods/Magiclysm/items/alchemy_items.json msgid "superior potion starter" msgid_plural "superior potion starters" -msgstr[0] "" +msgstr[0] "强效基础药剂" #. ~ Description for superior potion starter #: data/mods/Magiclysm/items/alchemy_items.json @@ -193666,7 +193951,7 @@ msgstr "充满魔法能量的纯净乙醇。聚集在其中的魔力使药剂表 #: data/mods/Magiclysm/items/alchemy_items.json msgid "large adrenal gland" msgid_plural "large adrenal glands" -msgstr[0] "" +msgstr[0] "大肾上腺" #. ~ Description for {'str': 'large adrenal gland'} #: data/mods/Magiclysm/items/alchemy_items.json @@ -193743,7 +194028,7 @@ msgstr "當鯊蜥獸在地底挖洞時,它的鰓會收集微量的貴重金屬 #: data/mods/Magiclysm/items/alchemy_items.json msgid "dragon essence" msgid_plural "dragon essences" -msgstr[0] "" +msgstr[0] "龙之精粹" #. ~ Description for dragon essence #: data/mods/Magiclysm/items/alchemy_items.json @@ -193755,7 +194040,7 @@ msgstr "這是龍的魔力精華,蒸餾成濃縮型態。" #: data/mods/Magiclysm/items/alchemy_items.json msgid "stirge proboscis" msgid_plural "stirge proboscises" -msgstr[0] "" +msgstr[0] "蚊蝠喙" #. ~ Description for {'str': 'stirge proboscis', 'str_pl': 'stirge #. proboscises'} @@ -193807,7 +194092,7 @@ msgstr "一支惡魔蜘蛛的獠牙。它仍然滴著毒藥;也許你在一些 #: data/mods/Magiclysm/items/ammo_types.json msgid "alumentum" msgid_plural "alumentum" -msgstr[0] "" +msgstr[0] "源动之焰" #. ~ Description for {'str_sp': 'alumentum'} #: data/mods/Magiclysm/items/alchemy_items.json @@ -193822,7 +194107,7 @@ msgstr "" #: data/mods/Magiclysm/items/alchemy_items.json msgid "mana dust" msgid_plural "mana dusts" -msgstr[0] "" +msgstr[0] "魔力之尘" #. ~ Description for mana dust #: data/mods/Magiclysm/items/alchemy_items.json @@ -193846,13 +194131,13 @@ msgstr[0] "污染的血液" #: data/mods/Magiclysm/items/fuel.json msgid "mana infused blood" msgid_plural "mana_infused_blood" -msgstr[0] "" +msgstr[0] "注魔之血" #: data/mods/Magiclysm/items/ammo_types.json #: data/mods/Magiclysm/items/archery.json msgid "orichalcum arrow" msgid_plural "orichalcum arrows" -msgstr[0] "" +msgstr[0] "山铜箭" #: data/mods/Magiclysm/items/ammo_types.json msgid "mercury" @@ -193881,7 +194166,7 @@ msgstr "由山铜制成的箭,正发出神秘的光芒。射击后有很大概 #: data/mods/Magiclysm/items/armor.json msgid "pair of demon chitin arm guards" msgid_plural "pairs of demon chitin arm guards" -msgstr[0] "" +msgstr[0] "恶魔甲壳护臂" #. ~ Description for {'str': 'pair of demon chitin arm guards', 'str_pl': #. 'pairs of demon chitin arm guards'} @@ -193894,7 +194179,7 @@ msgstr "一对由经过精心清理并裁剪过的恶魔蜘蛛躯壳制成的护 #: data/mods/Magiclysm/items/armor.json msgid "demon chitin armor" msgid_plural "demon chitin armors" -msgstr[0] "" +msgstr[0] "恶魔甲壳护甲" #. ~ Description for {'str': 'demon chitin armor'} #: data/mods/Magiclysm/items/armor.json @@ -193906,7 +194191,7 @@ msgstr "一副由经过精心清理并裁剪过的恶魔蜘蛛躯壳制成的全 #: data/mods/Magiclysm/items/armor.json msgid "demon chitin helmet" msgid_plural "demon chitin helmets" -msgstr[0] "" +msgstr[0] "恶魔甲壳头盔" #. ~ Description for {'str': 'demon chitin helmet'} #: data/mods/Magiclysm/items/armor.json @@ -193918,7 +194203,7 @@ msgstr "一顶由恶魔蜘蛛躯壳制成制成的头盔,能覆盖你的整个 #: data/mods/Magiclysm/items/armor.json msgid "pair of demon chitin gauntlets" msgid_plural "pairs of demon chitin gauntlets" -msgstr[0] "" +msgstr[0] "恶魔甲壳护手" #. ~ Description for {'str': 'pair of demon chitin gauntlets', 'str_pl': #. 'pairs of demon chitin gauntlets'} @@ -193931,7 +194216,7 @@ msgstr "一对由恶魔蜘蛛躯壳制成的护手,轻便耐用而且防火。 #: data/mods/Magiclysm/items/armor.json msgid "pair of demon chitin boots" msgid_plural "pairs of demon chitin boots" -msgstr[0] "" +msgstr[0] "恶魔甲壳靴" #. ~ Description for {'str': 'pair of demon chitin boots', 'str_pl': 'pairs of #. demon chitin boots'} @@ -193944,7 +194229,7 @@ msgstr "一对由恶魔蜘蛛躯壳制成的长靴,轻便耐用而且防火。 #: data/mods/Magiclysm/items/armor.json msgid "demon chitin dog mesh harness" msgid_plural "demon chitin dog mesh harnesses" -msgstr[0] "" +msgstr[0] "恶魔甲壳犬具" #. ~ Description for {'str': 'demon chitin dog mesh harness', 'str_pl': 'demon #. chitin dog mesh harnesses'} @@ -193957,7 +194242,7 @@ msgstr "一套自制的犬具,上面的恶魔甲壳片和薄薄的网状织物 #: data/mods/Magiclysm/items/armor.json msgid "demon chitin horse armor" msgid_plural "demon chitin horse armors" -msgstr[0] "" +msgstr[0] "恶魔甲壳马铠" #. ~ Description for {'str': 'demon chitin horse armor'} #: data/mods/Magiclysm/items/armor.json @@ -193978,7 +194263,7 @@ msgstr "科技魔法的最新进展使这个生化插件能够将血液中的固 #: data/mods/Magiclysm/items/bionics.json msgid "Crystallized Mana Nose Replacement" msgid_plural "Crystallized Mana Nose Replacements" -msgstr[0] "" +msgstr[0] "魔力结晶义鼻" #. ~ Description for {'str': 'Crystallized Mana Nose Replacement'} #: data/mods/Magiclysm/items/bionics.json @@ -194006,7 +194291,7 @@ msgstr "黑龍的鱗片。它仍保留原有的魔法性質與耐酸性。" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "raw black dragon hide" msgid_plural "raw black dragon hides" -msgstr[0] "" +msgstr[0] "生黑龙皮" #. ~ Description for raw black dragon hide #: data/mods/Magiclysm/items/black_dragon_items.json @@ -194146,7 +194431,7 @@ msgstr[0] "黑龍皮手套" #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonscale boots" msgid_plural "pairs of XL black dragonscale boots" -msgstr[0] "" +msgstr[0] "黑龙鳞靴(XL)" #. ~ Description for {'str': 'pair of XL black dragonscale boots', 'str_pl': #. 'pairs of XL black dragonscale boots'} @@ -194159,7 +194444,7 @@ msgstr "用黑龙鳞制成的特大码的靴子,经过精心剪裁能容下各 #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonhide boots" msgid_plural "pairs of XL black dragonhide boots" -msgstr[0] "" +msgstr[0] "黑龙皮靴(XL)" #. ~ Description for {'str': 'pair of XL black dragonhide boots', 'str_pl': #. 'pairs of XL black dragonhide boots'} @@ -194172,7 +194457,7 @@ msgstr "用黑龙皮制成的特大码的靴子,经过精心剪裁能容下各 #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonscale gauntlets" msgid_plural "pairs of XL black dragonscale gauntlets" -msgstr[0] "" +msgstr[0] "黑龙鳞护手(XL)" #. ~ Description for {'str': 'pair of XL black dragonscale gauntlets', #. 'str_pl': 'pairs of XL black dragonscale gauntlets'} @@ -194185,7 +194470,7 @@ msgstr "一对特大码的耐用护手,由黑龙鳞制成,用于双手或其 #: data/mods/Magiclysm/items/black_dragon_items.json msgid "pair of XL black dragonhide gloves" msgid_plural "pairs of XL black dragonhide gloves" -msgstr[0] "" +msgstr[0] "黑龙皮手套(XL)" #. ~ Description for {'str': 'pair of XL black dragonhide gloves', 'str_pl': #. 'pairs of XL black dragonhide gloves'} @@ -194199,7 +194484,7 @@ msgstr "一对特大码的耐用护手,由黑龙皮制成,用于双手或其 #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonscale helmet" msgid_plural "XL black dragonscale helmets" -msgstr[0] "" +msgstr[0] "黑龙鳞盔(XL)" #. ~ Description for {'str': 'XL black dragonscale helmet'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -194212,7 +194497,7 @@ msgstr "用黑龙鳞与黑龙皮制成的巨型头盔,全覆面设计,能容 #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonhide helmet" msgid_plural "XL black dragonhide helmets" -msgstr[0] "" +msgstr[0] "黑龙皮盔(XL)" #. ~ Description for {'str': 'XL black dragonhide helmet'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -194225,7 +194510,7 @@ msgstr "黑龙皮制成的巨型头盔,提供出色的头部防护,又不会 #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonscale armor" msgid_plural "XL black dragonscale armors" -msgstr[0] "" +msgstr[0] "黑龙鳞甲(XL)" #. ~ Description for {'str': 'XL black dragonscale armor'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -194238,7 +194523,7 @@ msgstr "特大码的全套黑龙鳞甲,部件覆盖躯干、腿、手臂,能 #: data/mods/Magiclysm/items/black_dragon_items.json msgid "XL black dragonhide armor" msgid_plural "XL black dragonhide armors" -msgstr[0] "" +msgstr[0] "黑龙皮甲(XL)" #. ~ Description for {'str': 'XL black dragonhide armor'} #: data/mods/Magiclysm/items/black_dragon_items.json @@ -194251,7 +194536,7 @@ msgstr "特大码的全套黑龙皮甲,部件覆盖躯干、腿、手臂,能 #: data/mods/Magiclysm/items/books_lore.json msgid "vacation brochure" msgid_plural "vacation brochures" -msgstr[0] "" +msgstr[0] "度假手册" #. ~ Use action message for vacation brochure. #. ~ Use action message for lair map. @@ -194272,7 +194557,7 @@ msgstr "" #: data/mods/Magiclysm/items/books_lore.json msgid "lair map" msgid_plural "lair maps" -msgstr[0] "" +msgstr[0] "巢穴地图" #. ~ Description for lair map #: data/mods/Magiclysm/items/books_lore.json @@ -194284,7 +194569,7 @@ msgstr "这是一张破旧的地图。它有一些奇形怪状的野兽的照片 #: data/mods/Magiclysm/items/books_lore.json msgid "old photo" msgid_plural "old photos" -msgstr[0] "" +msgstr[0] "旧照片" #. ~ Description for old photo #: data/mods/Magiclysm/items/books_lore.json @@ -194296,7 +194581,7 @@ msgstr "一张快乐的老巫师的照片,他似乎正在地下室里和一个 #: data/mods/Magiclysm/items/cast_spell_items.json msgid "lesser mana potion" msgid_plural "lesser mana potions" -msgstr[0] "" +msgstr[0] "次等魔力药剂" #. ~ Description for {'str': 'lesser mana potion'} #: data/mods/Magiclysm/items/cast_spell_items.json @@ -194308,17 +194593,17 @@ msgstr "你無法買到這東西,所以你需要留下來直到打最後首領 #: data/mods/Magiclysm/items/cast_spell_items.json msgid "mana potion" msgid_plural "mana potions" -msgstr[0] "" +msgstr[0] "魔力药剂" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "greater mana potion" msgid_plural "greater mana potions" -msgstr[0] "" +msgstr[0] "高等魔力药剂" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Cat's Grace" msgid_plural "potions of Cat's Grace" -msgstr[0] "" +msgstr[0] "猫之优雅药剂" #. ~ Description for {'str': "potion of Cat's Grace", 'str_pl': "potions of #. Cat's Grace"} @@ -194331,7 +194616,7 @@ msgstr "貓之優雅藥劑,能夠增加你的敏捷 10 分鐘。" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Ogre's Strength" msgid_plural "potions of Ogre's Strength" -msgstr[0] "" +msgstr[0] "巨魔之力药剂" #. ~ Description for {'str': "potion of Ogre's Strength", 'str_pl': "potions #. of Ogre's Strength"} @@ -194344,7 +194629,7 @@ msgstr "食人魔之力藥劑,能夠增加你的力量 10 分鐘。" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Eagle's Sight" msgid_plural "potions of Eagle's Sight" -msgstr[0] "" +msgstr[0] "鹰眼药剂" #. ~ Description for {'str': "potion of Eagle's Sight", 'str_pl': "potions of #. Eagle's Sight"} @@ -194357,7 +194642,7 @@ msgstr "鷹之視野藥劑。能夠增加你的感知 10 分鐘。" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Fox's Cunning" msgid_plural "potions of Fox's Cunning" -msgstr[0] "" +msgstr[0] "狐之狡黠药剂" #. ~ Description for {'str': "potion of Fox's Cunning", 'str_pl': "potions of #. Fox's Cunning"} @@ -194370,7 +194655,7 @@ msgstr "狐之狡滑藥劑,能夠增加你的智力 10 分鐘。" #: data/mods/Magiclysm/items/cast_spell_items.json msgid "zombie voodoo doll" msgid_plural "zombie voodoo dolls" -msgstr[0] "" +msgstr[0] "丧尸巫毒娃娃" #. ~ Description for zombie voodoo doll #: data/mods/Magiclysm/items/cast_spell_items.json @@ -194383,7 +194668,7 @@ msgstr "一個維妙維肖的不死人類模型,包括骨頭和器官。死靈 #: data/mods/Magiclysm/items/cast_spell_items.json msgid "ossified voodoo doll" msgid_plural "ossified voodoo dolls" -msgstr[0] "" +msgstr[0] "骨片巫毒娃娃" #. ~ Description for ossified voodoo doll #: data/mods/Magiclysm/items/cast_spell_items.json @@ -194397,7 +194682,7 @@ msgstr "一個維妙維肖被骨頭包覆的不死人類模型,包括器官。 #: data/mods/Magiclysm/items/cast_spell_items.json msgid "cougar voodoo doll" msgid_plural "cougar voodoo dolls" -msgstr[0] "" +msgstr[0] "美洲狮巫毒娃娃" #. ~ Description for cougar voodoo doll #: data/mods/Magiclysm/items/cast_spell_items.json @@ -194410,7 +194695,7 @@ msgstr "一個維妙維肖的不死美洲獅模型,包括毛皮、骨骼和器 #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Twisted Restoration" msgid_plural "potions of Twisted Restoration" -msgstr[0] "" +msgstr[0] "扭曲恢复药剂" #. ~ Description for {'str': 'potion of Twisted Restoration', 'str_pl': #. 'potions of Twisted Restoration'} @@ -194424,7 +194709,7 @@ msgstr "這種惡臭的液體用加速你的心跳達到危險等級的方式來 #: data/mods/Magiclysm/items/cast_spell_items.json msgid "potion of Improved Twisted Restoration" msgid_plural "potions of Improved Twisted Restoration" -msgstr[0] "" +msgstr[0] "改良扭曲恢复药剂" #. ~ Description for {'str': 'potion of Improved Twisted Restoration', #. 'str_pl': 'potions of Improved Twisted Restoration'} @@ -194549,7 +194834,7 @@ msgstr "这块注魔的小石块上面有一个像炼金术和魔药的符号。 #: data/mods/Magiclysm/items/comestibles.json msgid "owlbear egg" msgid_plural "owlbear eggs" -msgstr[0] "" +msgstr[0] "枭熊蛋" #. ~ Description for owlbear egg #: data/mods/Magiclysm/items/comestibles.json @@ -194565,7 +194850,7 @@ msgstr "" #: data/mods/Magiclysm/items/comestibles.json msgid "owlbear egg yolk" msgid_plural "owlbear egg yolks" -msgstr[0] "" +msgstr[0] "枭熊蛋蛋黄" #. ~ Description for owlbear egg yolk #: data/mods/Magiclysm/items/comestibles.json @@ -194575,7 +194860,7 @@ msgstr "鴞熊蛋內的液體。好吃。" #: data/mods/Magiclysm/items/comestibles.json msgid "hairball" msgid_plural "hairballs" -msgstr[0] "" +msgstr[0] "毛团" #. ~ Description for {'str': 'hairball'} #: data/mods/Magiclysm/items/comestibles.json @@ -194599,7 +194884,7 @@ msgstr "來自被殺死的龍的肉。無法用平常的烹飪方式處理它, #: data/mods/Magiclysm/items/comestibles.json msgid "scream mushroom" msgid_plural "scream mushrooms" -msgstr[0] "" +msgstr[0] "尖叫蘑菇" #. ~ Description for scream mushroom #: data/mods/Magiclysm/items/comestibles.json @@ -194610,7 +194895,7 @@ msgstr "從死亡尖叫者收穫而來的蘑菇。可以用來製作藥劑。" #: data/mods/Magiclysm/items/comestibles.json msgid "purified meat" msgid_plural "purified meats" -msgstr[0] "" +msgstr[0] "净化肉" #. ~ Description for purified meat #: data/mods/Magiclysm/items/comestibles.json @@ -194622,7 +194907,7 @@ msgstr "和大灾变前实验室培育的牛肉没有区别。本来它应该是 #: data/mods/Magiclysm/items/comestibles.json msgid "impure meat" msgid_plural "impure meats" -msgstr[0] "" +msgstr[0] "未净肉" #. ~ Description for impure meat #: data/mods/Magiclysm/items/comestibles.json @@ -194635,7 +194920,7 @@ msgstr "虽然不像之前那样被感染,尝起来也和真肉一样。但你 #: data/mods/Magiclysm/items/constructs.json msgid "broken clay golem" msgid_plural "broken clay golems" -msgstr[0] "" +msgstr[0] "粘土傀儡(损坏)" #. ~ Description for broken clay golem #: data/mods/Magiclysm/items/constructs.json @@ -194647,7 +194932,7 @@ msgstr "一个损坏的粘土傀儡,看起来像一件后现代艺术品。打 #: data/mods/Magiclysm/items/constructs.json msgid "broken plastic golem" msgid_plural "broken plastic golems" -msgstr[0] "" +msgstr[0] "塑料傀儡(损坏)" #. ~ Description for broken plastic golem #: data/mods/Magiclysm/items/constructs.json @@ -194659,7 +194944,7 @@ msgstr "一个损坏的塑料傀儡,就像一个巨大的人偶被一只同样 #: data/mods/Magiclysm/items/constructs.json msgid "broken stone golem" msgid_plural "broken stone golems" -msgstr[0] "" +msgstr[0] "石傀儡(损坏)" #. ~ Description for broken stone golem #: data/mods/Magiclysm/items/constructs.json @@ -194671,7 +194956,7 @@ msgstr "一个损坏的石傀儡,看起来像一件后现代艺术品。打碎 #: data/mods/Magiclysm/items/constructs.json msgid "broken iron golem" msgid_plural "broken iron golems" -msgstr[0] "" +msgstr[0] "铁傀儡(损坏)" #. ~ Description for broken iron golem #: data/mods/Magiclysm/items/constructs.json @@ -194693,7 +194978,7 @@ msgstr[0] "急速腰帶" #: data/mods/Magiclysm/items/enchanted.json msgid "lesser staff of the magi" msgid_plural "lesser staves of the magi" -msgstr[0] "" +msgstr[0] "次等法师法杖" #. ~ Description for {'str': 'lesser staff of the magi', 'str_pl': 'lesser #. staves of the magi'} @@ -194733,12 +195018,12 @@ msgstr[0] "魔法皮帶" #: data/mods/Magiclysm/items/enchanted_belts.json msgid "Belt of Haste" msgid_plural "Belts of Haste" -msgstr[0] "" +msgstr[0] "迅捷腰带" #: data/mods/Magiclysm/items/enchanted_belts.json msgid "Megingjörð" msgid_plural "Megingjörð" -msgstr[0] "" +msgstr[0] "索尔的神奇腰带" #. ~ Description for {'str_sp': 'Megingjörð'} #: data/mods/Magiclysm/items/enchanted_belts.json @@ -194750,7 +195035,7 @@ msgstr "传说中雷神索尔的神奇腰带,至少看起来是这样的。它 #: data/mods/Magiclysm/items/enchanted_belts.json msgid "Lesser Girdle of Pockets" msgid_plural "Lesser Girdles of Pockets" -msgstr[0] "" +msgstr[0] "次级口袋腰带" #. ~ Description for {'str': 'Lesser Girdle of Pockets', 'str_pl': 'Lesser #. Girdles of Pockets'} @@ -194766,12 +195051,12 @@ msgstr "一条很适合你腰部的宽腰带,上面覆盖着许多小口袋, #: data/mods/Magiclysm/items/enchanted_belts.json msgid "Greater Girdle of Pockets" msgid_plural "Greater Girdles of Pockets" -msgstr[0] "" +msgstr[0] "高级口袋腰带" #: data/mods/Magiclysm/items/enchanted_belts.json msgid "Belt of Weaponry" msgid_plural "Belts of Weaponry" -msgstr[0] "" +msgstr[0] "武器腰带" #. ~ Description for {'str': 'Belt of Weaponry', 'str_pl': 'Belts of #. Weaponry'} @@ -194785,7 +195070,7 @@ msgstr "合身地環繞在你腰部的寬腰帶,你可以在眨眼間將任何 #: data/mods/Magiclysm/items/enchanted_belts.json msgid "technomancer's toolbelt" msgid_plural "technomancer's toolbelts" -msgstr[0] "" +msgstr[0] "科技法师工具腰带" #. ~ Description for {'str': "technomancer's toolbelt"} #: data/mods/Magiclysm/items/enchanted_belts.json @@ -194818,7 +195103,7 @@ msgstr "一根看上去似由金属编织而成但又十分灵活的皮带。你 #: data/mods/Magiclysm/items/enchanted_belts.json msgid "The Iron Whip" msgid_plural "Iron Whips" -msgstr[0] "" +msgstr[0] "铁鞭" #. ~ Use action msg for {'str': 'The Iron Whip', 'str_pl': 'Iron Whips'}. #: data/mods/Magiclysm/items/enchanted_belts.json @@ -194838,7 +195123,7 @@ msgstr "一条编织而成、柔软灵活的钢铁长鞭,末端变成锋利的 #: data/mods/Magiclysm/items/enchanted_boots.json msgid "seven league boots" msgid_plural "pairs of seven league boots" -msgstr[0] "" +msgstr[0] "七里靴" #. ~ Description for {'str': 'seven league boots', 'str_pl': 'pairs of seven #. league boots'} @@ -194854,7 +195139,7 @@ msgstr "一双十分坚固却又非常舒适合身的旧钢头皮靴,看上去 #: data/mods/Magiclysm/items/enchanted_boots.json msgid "boots of haste" msgid_plural "pairs of boots of haste" -msgstr[0] "" +msgstr[0] "加速靴" #: data/mods/Magiclysm/items/enchanted_boots.json msgid "escape boots" @@ -194872,7 +195157,7 @@ msgstr "即使表面破舊,但是磨損的皮革跟鋼鐵卻非常舒適且合 #: data/mods/Magiclysm/items/enchanted_boots.json msgid "boots of grounding" msgid_plural "pairs of boots of grounding" -msgstr[0] "" +msgstr[0] "立地靴" #. ~ Description for {'str': 'boots of grounding', 'str_pl': 'pairs of boots #. of grounding'} @@ -194962,7 +195247,7 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "'Silent Winds' suppressor" msgid_plural "'Silent Winds' suppressors" -msgstr[0] "" +msgstr[0] "\"静风\"消音器" #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "" @@ -194973,7 +195258,7 @@ msgstr "除了消音材料之外,这个消音器还含有一个小范围静音 #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "mana laser sight (rail)" msgid_plural "mana laser sights (rail)" -msgstr[0] "" +msgstr[0] "魔法激光瞄具(导轨)" #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "" @@ -194987,7 +195272,7 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "mana laser sight (underbarrel)" msgid_plural "mana laser sights (underbarrel)" -msgstr[0] "" +msgstr[0] "魔法激光瞄具(管下)" #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "" @@ -195001,7 +195286,7 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "mana dot sight" msgid_plural "mana dot sights" -msgstr[0] "" +msgstr[0] "魔法蓝点瞄准镜" #: data/mods/Magiclysm/items/enchanted_gunmods.json msgid "" @@ -195096,6 +195381,16 @@ msgid "sledge hammer +2" msgid_plural "sledge hammer +2s" msgstr[0] "大鎚 +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +1" +msgid_plural "heavy sledge hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "heavy sledge hammer +2" +msgid_plural "heavy sledge hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "warhammer +1" msgid_plural "warhammer +1s" @@ -195267,11 +195562,13 @@ msgid_plural "cavalry sabre +2s" msgstr[0] "騎兵軍刀 +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +1" msgid_plural "crowbar +1s" msgstr[0] "撬棍 +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "crowbar +2" msgid_plural "crowbar +2s" msgstr[0] "撬棍 +2" @@ -195317,11 +195614,13 @@ msgid_plural "combat knife +2s" msgstr[0] "戰鬥刀 +2" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +1" msgid_plural "hunting knife +1s" msgstr[0] "獵刀 +1" #: data/mods/Magiclysm/items/enchanted_melee.json +#: data/mods/Magiclysm/items/enchanted_tools.json msgid "hunting knife +2" msgid_plural "hunting knife +2s" msgstr[0] "獵刀 +2" @@ -195466,6 +195765,16 @@ msgid "dao +2" msgid_plural "dao +2s" msgstr[0] "中式刀 +2" +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +1" +msgid_plural "lucerne hammers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_melee.json +msgid "lucerne hammer +2" +msgid_plural "lucerne hammers +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_melee.json msgid "Biomancer spear" msgid_plural "Biomancer spears" @@ -195543,7 +195852,7 @@ msgstr "鋼製的儀式用小刀,泛靈論者在召喚時用來放血的器具 #: data/mods/Magiclysm/items/enchanted_melee.json msgid "springstaff(baton)" msgid_plural "springstaves(baton)" -msgstr[0] "" +msgstr[0] "弹簧长杖(甩棍)" #. ~ Use action menu_text for {'str': 'springstaff(baton)', 'str_pl': #. 'springstaves(baton)'}. @@ -195568,7 +195877,7 @@ msgstr "这种多用途武器使用科技魔法增强过的弹簧以保持长杖 #: data/mods/Magiclysm/items/enchanted_melee.json msgid "springstaff(staff)" msgid_plural "springstaves(staff)" -msgstr[0] "" +msgstr[0] "弹簧长杖(长杖)" #. ~ Use action menu_text for {'str': 'springstaff(staff)', 'str_pl': #. 'springstaves(staff)'}. @@ -195593,7 +195902,7 @@ msgstr "这种多用途武器使用科技魔法增强过的弹簧以保持长杖 #: data/mods/Magiclysm/items/enchanted_misc.json msgid "heat cube" msgid_plural "heat cubes" -msgstr[0] "" +msgstr[0] "热立方" #. ~ Use action menu_text for heat cube. #: data/mods/Magiclysm/items/enchanted_misc.json @@ -195617,7 +195926,7 @@ msgstr "一个有你拳头大的光滑钢制立方体,上面有数个按钮, #: data/mods/Magiclysm/items/enchanted_misc.json msgid "heat cube (torch on)" msgid_plural "heat cubes (torch on)" -msgstr[0] "" +msgstr[0] "热立方(点亮)" #. ~ Use action msg for {'str': 'heat cube (torch on)', 'str_pl': 'heat cubes #. (torch on)'}. @@ -195636,7 +195945,7 @@ msgstr "热立方目前处于火炬模式,正发出一道温暖的闪耀火焰 #: data/mods/Magiclysm/items/enchanted_misc.json msgid "skeleton key of opening" msgid_plural "skeleton keys of opening" -msgstr[0] "" +msgstr[0] "魔法万能钥匙" #. ~ Description for {'str': 'skeleton key of opening', 'str_pl': 'skeleton #. keys of opening'} @@ -195648,7 +195957,7 @@ msgstr "一把金制万能钥匙。你可以用它来开锁。" #: data/mods/Magiclysm/items/enchanted_misc.json msgid "everburning torch" msgid_plural "everburning torches" -msgstr[0] "" +msgstr[0] "不灭火炬" #. ~ Description for {'str': 'everburning torch', 'str_pl': 'everburning #. torches'} @@ -195716,7 +196025,7 @@ msgstr "一把采用多种材料复合制成以增加储能效率的弓。弓背 #: data/mods/Magiclysm/items/enchanted_ranged.json msgid "M47A1 Techno-Medusa" msgid_plural "M47A1 Techno-Medusae" -msgstr[0] "" +msgstr[0] "M47A1 科技魔法\"美杜莎\"左轮手枪" #: data/mods/Magiclysm/items/enchanted_ranged.json msgid "" @@ -195731,7 +196040,7 @@ msgstr "" #: data/mods/Magiclysm/items/enchanted_ranged.json msgid "gunblade" msgid_plural "gunblades" -msgstr[0] "" +msgstr[0] "枪刃" #: data/mods/Magiclysm/items/enchanted_ranged.json msgid "" @@ -195785,7 +196094,7 @@ msgstr "一枚雕有匕首的華麗銀戒指,使用後會幻化成一把在你 #: data/mods/Magiclysm/items/enchanted_rings.json msgid "eel ring" msgid_plural "eel rings" -msgstr[0] "" +msgstr[0] "鳗鱼戒指" #. ~ Description for eel ring #: data/mods/Magiclysm/items/enchanted_rings.json @@ -195797,7 +196106,7 @@ msgstr "一个轻薄的银戒指,上面画着一条鳗鱼。让你每回合额 #: data/mods/Magiclysm/items/enchanted_rings.json msgid "bicephalous eel ring" msgid_plural "bicephalous eel rings" -msgstr[0] "" +msgstr[0] "双头鳗鱼戒指" #. ~ Description for {'str': 'bicephalous eel ring'} #: data/mods/Magiclysm/items/enchanted_rings.json @@ -195809,7 +196118,7 @@ msgstr "一个轻薄的金戒指,上面画着一条盘绕在自己身上的双 #: data/mods/Magiclysm/items/enchanted_rings.json msgid "ring of strength +1" msgid_plural "rings of strength +1" -msgstr[0] "" +msgstr[0] "力量戒指 +1" #. ~ Description for {'str': 'ring of strength +1', 'str_pl': 'rings of #. strength +1'} @@ -196298,6 +196607,66 @@ msgid "" "turns into the item pictured on the front, in this case a crowbar." msgstr "一枚大銀幣,當說出其背面刻印的字詞時,代幣會被觸發變成正面刻印圖示的物品,此代幣圖示為撬棍。" +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +1" +msgid_plural "bottle jacks +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "bottle jack +2" +msgid_plural "bottle jacks +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +1" +msgid_plural "scalpels +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "scalpel +2" +msgid_plural "scalpels +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +1" +msgid_plural "butcher knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butcher knife +2" +msgid_plural "butcher knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +1" +msgid_plural "meat cleavers +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "meat cleaver +2" +msgid_plural "meat cleavers +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +1" +msgid_plural "carving knives +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "carving knife +2" +msgid_plural "carving knives +2" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +1" +msgid_plural "butchering kits +1" +msgstr[0] "" + +#: data/mods/Magiclysm/items/enchanted_tools.json +msgid "butchering kit +2" +msgid_plural "butchering kits +2" +msgstr[0] "" + #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "cestus +1" msgid_plural "cestus +1s" @@ -196347,7 +196716,7 @@ msgstr "一雙巨大的發光金屬重型長手套,表面鑲滿著魔法符號 #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "shotcestus" msgid_plural "shotcesti" -msgstr[0] "" +msgstr[0] "霰弹拳套" #: data/mods/Magiclysm/items/enchanted_unarmed.json msgid "" @@ -196706,7 +197075,7 @@ msgstr[0] "一次性的冷錐術高級魔杖" #: data/mods/Magiclysm/items/ethereal_items.json msgid "pair of magical armored stone gauntlets" msgid_plural "pairs of magical armored stone gauntlets" -msgstr[0] "" +msgstr[0] "魔石护手" #. ~ Description for {'str': 'pair of magical armored stone gauntlets', #. 'str_pl': 'pairs of magical armored stone gauntlets'} @@ -196749,7 +197118,7 @@ msgstr "可用於閱讀的小魔法燈。" #: data/mods/Magiclysm/items/ethereal_items.json msgid "large shield of magical ice" msgid_plural "large shields of magical ice" -msgstr[0] "" +msgstr[0] "魔法大冰盾" #. ~ Description for {'str': 'large shield of magical ice', 'str_pl': 'large #. shields of magical ice'} @@ -196760,7 +197129,7 @@ msgstr "輕巧但堅韌的盾牌,完全由魔法冰製成。" #: data/mods/Magiclysm/items/ethereal_items.json msgid "slick icy coatings" msgid_plural "slick icy coatings" -msgstr[0] "" +msgstr[0] "光滑冰层" #. ~ Description for {'str_sp': 'slick icy coatings'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -196809,7 +197178,7 @@ msgstr "一條扭曲的長觸手,上面覆蓋著鋒利的骨狀刃片和突起 #: data/mods/Magiclysm/items/ethereal_items.json msgid "flesh pouch" msgid_plural "flesh pouches" -msgstr[0] "" +msgstr[0] "肉身成袋" #. ~ Description for {'str': 'flesh pouch', 'str_pl': 'flesh pouches'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -196832,7 +197201,7 @@ msgstr "這是一種完全由骨骼製成的邪惡的長矛/戟混合體。" #: data/mods/Magiclysm/items/ethereal_items.json msgid "Woodbow" msgid_plural "Woodbows" -msgstr[0] "" +msgstr[0] "木弓" #: data/mods/Magiclysm/items/ethereal_items.json msgid "" @@ -196843,7 +197212,7 @@ msgstr "一把魔法生成的华丽反曲弓。由结实而有弹性的木料制 #: data/mods/Magiclysm/items/ethereal_items.json msgid "seed of purification" msgid_plural "seeds of purification" -msgstr[0] "" +msgstr[0] "净化之种" #. ~ Use action menu_text for {'str': 'seed of purification', 'str_pl': 'seeds #. of purification'}. @@ -196879,7 +197248,7 @@ msgstr "這細粉微微發光,越來越亮" #: data/mods/Magiclysm/items/ethereal_items.json msgid "obfuscating aura" msgid_plural "obfuscating auras" -msgstr[0] "" +msgstr[0] "朦胧光环" #. ~ Description for obfuscating aura #: data/mods/Magiclysm/items/ethereal_items.json @@ -196891,7 +197260,7 @@ msgstr "一个覆盖全身、看不见的魔法光环扭曲了你身体周围的 #: data/mods/Magiclysm/items/ethereal_items.json msgid "acid resistance aura" msgid_plural "acid resistance auras" -msgstr[0] "" +msgstr[0] "防酸光环" #. ~ Description for {'str': 'acid resistance aura'} #. ~ Description for greater acid resistance aura @@ -196902,12 +197271,12 @@ msgstr "一个覆盖全身的肉眼无法看见的防酸光环。" #: data/mods/Magiclysm/items/ethereal_items.json msgid "greater acid resistance aura" msgid_plural "greater acid resistance auras" -msgstr[0] "" +msgstr[0] "高等防酸光环" #: data/mods/Magiclysm/items/ethereal_items.json msgid "frost armor" msgid_plural "frost armor" -msgstr[0] "" +msgstr[0] "寒霜盔甲" #. ~ Description for {'str_sp': 'frost armor'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -196917,7 +197286,7 @@ msgstr "一层包覆全身的、薄薄的魔法冰层。" #: data/mods/Magiclysm/items/ethereal_items.json msgid "stoneskin coating" msgid_plural "stoneskin coating" -msgstr[0] "" +msgstr[0] "石化皮肤" #. ~ Description for {'str_sp': 'stoneskin coating'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -196929,7 +197298,7 @@ msgstr "一层覆盖全身的薄薄的不断移动的岩石,仿佛是有生命 #: data/mods/Magiclysm/items/ethereal_items.json msgid "overcharge burn" msgid_plural "overcharge burns" -msgstr[0] "" +msgstr[0] "过载烧伤" #. ~ Description for {'str': 'overcharge burn'} #: data/mods/Magiclysm/items/ethereal_items.json @@ -196939,7 +197308,7 @@ msgstr "哎哟,这可是太聪明了!也许它很快就会消退?" #: data/mods/Magiclysm/items/ethereal_items.json msgid "aura of protection" msgid_plural "auras of protection" -msgstr[0] "" +msgstr[0] "保护光环" #. ~ Description for {'str': 'aura of protection', 'str_pl': 'auras of #. protection'} @@ -197025,7 +197394,7 @@ msgstr "" #: data/mods/Magiclysm/items/melee.json msgid "Gram" msgid_plural "Grams" -msgstr[0] "" +msgstr[0] "Gram,胜利之剑" #. ~ Description for {'str': 'Gram'} #: data/mods/Magiclysm/items/melee.json @@ -197052,7 +197421,7 @@ msgstr "" #: data/mods/Magiclysm/items/melee.json msgid "orichalcum combat knife" msgid_plural "orichalcum combat knives" -msgstr[0] "" +msgstr[0] "山铜战术匕首" #. ~ Description for {'str': 'orichalcum combat knife', 'str_pl': 'orichalcum #. combat knives'} @@ -197066,7 +197435,7 @@ msgstr "一把由山铜而不是钢材制成的战术匕首。山铜制品比钢 #: data/mods/Magiclysm/items/melee.json msgid "orichalcum longsword" msgid_plural "orichalcum longswords" -msgstr[0] "" +msgstr[0] "山铜长剑" #. ~ Description for {'str': 'orichalcum longsword'} #: data/mods/Magiclysm/items/melee.json @@ -197079,7 +197448,7 @@ msgstr "一把由山铜而不是钢材制成的长剑。山铜制品比钢更锋 #: data/mods/Magiclysm/items/melee.json msgid "orichalcum fire axe" msgid_plural "orichalcum fire axes" -msgstr[0] "" +msgstr[0] "山铜消防斧" #. ~ Description for {'str': 'orichalcum fire axe'} #: data/mods/Magiclysm/items/melee.json @@ -197092,7 +197461,7 @@ msgstr "一把由山铜而不是钢材制成的消防斧。这让它能够砍开 #: data/mods/Magiclysm/items/metals.json msgid "lump of orichalcum" msgid_plural "lumps of orichalcum" -msgstr[0] "" +msgstr[0] "山铜块" #. ~ Description for {'str': 'lump of orichalcum', 'str_pl': 'lumps of #. orichalcum'} @@ -197104,7 +197473,7 @@ msgstr "一块未经过处理的山铜。需要先将其打造成锭才能进一 #: data/mods/Magiclysm/items/metals.json msgid "sliver of orichalcum" msgid_plural "slivers of orichalcum" -msgstr[0] "" +msgstr[0] "山铜片" #. ~ Description for {'str': 'sliver of orichalcum', 'str_pl': 'slivers of #. orichalcum'} @@ -197117,7 +197486,7 @@ msgstr "一块未经过处理的山铜碎片。需要先将其打造成锭才能 #: data/mods/Magiclysm/items/metals.json msgid "orichalcum ingot" msgid_plural "orichalcum ingots" -msgstr[0] "" +msgstr[0] "山铜锭" #. ~ Description for orichalcum ingot #: data/mods/Magiclysm/items/metals.json @@ -197129,7 +197498,7 @@ msgstr "一块山铜锭。约有3x7x12厘米大小,能够被用来锻造成各 #: data/mods/Magiclysm/items/metals.json msgid "liquid mercury" msgid_plural "liquid mercury" -msgstr[0] "" +msgstr[0] "液态汞" #. ~ Description for {'str_sp': 'liquid mercury'} #: data/mods/Magiclysm/items/metals.json @@ -197139,7 +197508,7 @@ msgstr "液态的汞元素,以其在温度计中的使用而闻名。" #: data/mods/Magiclysm/items/mutagen.json msgid "concentrated mana serum" msgid_plural "concentrated mana serums" -msgstr[0] "" +msgstr[0] "浓缩魔力血清" #. ~ Description for concentrated mana serum #: data/mods/Magiclysm/items/mutagen.json @@ -197151,7 +197520,7 @@ msgstr "一种高度浓缩的魔法药剂。你不太确定它的效果都有什 #: data/mods/Magiclysm/items/obsolete.json msgid "wand of fireballs" msgid_plural "wands of fireballs" -msgstr[0] "" +msgstr[0] "火球法杖" #. ~ Description for {'str': 'wand of fireballs', 'str_pl': 'wands of #. fireballs'} @@ -197164,7 +197533,7 @@ msgstr "這是一款經典的魔杖,可以不失誤地施展火球術。技藝 #: data/mods/Magiclysm/items/obsolete.json msgid "wand of magic missiles" msgid_plural "wands of magic missiles" -msgstr[0] "" +msgstr[0] "魔法飞弹法杖" #. ~ Description for {'str': 'wand of magic missiles', 'str_pl': 'wands of #. magic missiles'} @@ -197217,7 +197586,7 @@ msgstr "一本平裝魔典,記述將不死生物靈魂綁定到玩偶的技藝 #: data/mods/Magiclysm/items/recipe_books.json msgid "Magitek Illustrated" msgid_plural "copies of Magitek Illustrated" -msgstr[0] "" +msgstr[0] "魔法科技图解" #. ~ Description for {'str': 'Magitek Illustrated', 'str_pl': 'copies of #. Magitek Illustrated'} @@ -197233,7 +197602,7 @@ msgstr "" #: data/mods/Magiclysm/items/recipe_books.json msgid "The Weapons of Asgard and Beyond" msgid_plural "copies of The Weapons of Asgard and Beyond" -msgstr[0] "" +msgstr[0] "阿斯加德之武" #. ~ Description for {'str': 'The Weapons of Asgard and Beyond', 'str_pl': #. 'copies of The Weapons of Asgard and Beyond'} @@ -197247,7 +197616,7 @@ msgstr "一本精美华丽的古书,似乎是用北欧符文写的。从书中 #: data/mods/Magiclysm/items/recipe_books.json msgid "Cooking with Poison" msgid_plural "copies of Cooking with Poison" -msgstr[0] "" +msgstr[0] "与毒共煮" #. ~ Description for {'str': 'Cooking with Poison', 'str_pl': 'copies of #. Cooking with Poison'} @@ -197260,7 +197629,7 @@ msgstr "一本皮面精装书,封面上有个凸印的大锅图案。书中详 #: data/mods/Magiclysm/items/recipe_books.json msgid "Metals of Legend" msgid_plural "copies of Metals of Legend" -msgstr[0] "" +msgstr[0] "传奇炼金者手册" #. ~ Description for {'str': 'Metals of Legend', 'str_pl': 'copies of Metals #. of Legend'} @@ -197274,7 +197643,7 @@ msgstr "一本有着黄铜板封面的书。它号称能够教人如何制造山 #: data/mods/Magiclysm/items/recipe_books.json msgid "Protection from Magical Beasts" msgid_plural "copies of Protection from Magical Beasts" -msgstr[0] "" +msgstr[0] "魔法生物防护手册" #. ~ Description for {'str': 'Protection from Magical Beasts', 'str_pl': #. 'copies of Protection from Magical Beasts'} @@ -197285,6 +197654,19 @@ msgid "" "protective equipment inside." msgstr "一本皮革装订的书,封面上画着一个盾牌挡住了龙炎。里面描述了把各种怪物毛皮制成防护装备的方法。" +#: data/mods/Magiclysm/items/recipe_books.json +msgid "Enchanter's Guidebook" +msgid_plural "copies of Enchanter's Guidebooks" +msgstr[0] "" + +#. ~ Description for {'str': "Enchanter's Guidebook", 'str_pl': "copies of +#. Enchanter's Guidebooks"} +#: data/mods/Magiclysm/items/recipe_books.json +msgid "" +"A hefty textbook on the theory and practice of magically strengthening " +"weapons and tools." +msgstr "" + #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Spell Scroll" msgid_plural "Spell Scrolls" @@ -197293,7 +197675,7 @@ msgstr[0] "法術卷軸" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Crystallize Mana" msgid_plural "Scrolls of Crystallize Mana" -msgstr[0] "" +msgstr[0] "魔力结晶卷轴" #. ~ Description for {'str': 'Scroll of Crystallize Mana', 'str_pl': 'Scrolls #. of Crystallize Mana'} @@ -197305,7 +197687,7 @@ msgstr "一名合格的巫师永远准备周全,把你的魔力结晶化以留 #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Dark Sight" msgid_plural "Scrolls of Dark Sight" -msgstr[0] "" +msgstr[0] "黑暗视觉卷轴" #. ~ Description for {'str': 'Scroll of Dark Sight', 'str_pl': 'Scrolls of #. Dark Sight'} @@ -197318,7 +197700,7 @@ msgstr "在此奧術之前黑暗無所遁藏。調整你的視覺成完美夜視 #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Invisibility" msgid_plural "Scrolls of Invisibility" -msgstr[0] "" +msgstr[0] "隐身术卷轴" #. ~ Description for {'str': 'Scroll of Invisibility', 'str_pl': 'Scrolls of #. Invisibility'} @@ -197331,7 +197713,7 @@ msgstr "没有你的允许,光将不会与你发生作用。隐身!" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Obfuscated Body" msgid_plural "Scrolls of Obfuscated Body" -msgstr[0] "" +msgstr[0] "朦胧术卷轴" #. ~ Description for {'str': 'Scroll of Obfuscated Body', 'str_pl': 'Scrolls #. of Obfuscated Body'} @@ -197344,382 +197726,382 @@ msgstr "一个魔法光环扭曲了你身体周围的光线,使你更容易闪 #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Holographic Transposition" msgid_plural "Scrolls of Holographic Transposition" -msgstr[0] "" +msgstr[0] "全息换位术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Smite" msgid_plural "Scrolls of Smite" -msgstr[0] "" +msgstr[0] "神圣惩击卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Life Conversion" msgid_plural "Scrolls of Life Conversion" -msgstr[0] "" +msgstr[0] "生命分流卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Mind Over Pain" msgid_plural "Scrolls of Mind Over Pain" -msgstr[0] "" +msgstr[0] "心胜于痛卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Summon Zombie" msgid_plural "Scrolls of Summon Zombie" -msgstr[0] "" +msgstr[0] "召唤丧尸卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Summon Skeleton" msgid_plural "Scrolls of Summon Skeleton" -msgstr[0] "" +msgstr[0] "召唤骷髅卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Summon Floating Disk" msgid_plural "Scrolls of Summon Floating Disk" -msgstr[0] "" +msgstr[0] "召唤飘浮碟卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Summon Decayed Pouncer" msgid_plural "Scrolls of Summon Decayed Pouncer" -msgstr[0] "" +msgstr[0] "召唤腐朽突袭兽卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Cure Light Wounds" msgid_plural "Scrolls of Cure Light Wounds" -msgstr[0] "" +msgstr[0] "治疗轻伤卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Pain Split" msgid_plural "Scrolls of Pain Split" -msgstr[0] "" +msgstr[0] "伤痛分流卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Vicious Tentacle" msgid_plural "Scrolls of Vicious Tentacle" -msgstr[0] "" +msgstr[0] "残暴之鞭卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Grotesque Enhancement" msgid_plural "Scrolls of Grotesque Enhancement" -msgstr[0] "" +msgstr[0] "扭曲强化卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Acidic Spray" msgid_plural "Scrolls of Acidic Spray" -msgstr[0] "" +msgstr[0] "酸液喷射卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Flesh Pouch" msgid_plural "Scrolls of Flesh Pouch" -msgstr[0] "" +msgstr[0] "肉身成袋卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Conjure Bonespear" msgid_plural "Scrolls of Conjure Bonespear" -msgstr[0] "" +msgstr[0] "白骨之矛卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Megablast" msgid_plural "Scrolls of Megablast" -msgstr[0] "" +msgstr[0] "炽能冲击卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Magical Light" msgid_plural "Scrolls of Magical Light" -msgstr[0] "" +msgstr[0] "魔法阅读灯卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Blinding Flash" msgid_plural "Scrolls of Blinding Flash" -msgstr[0] "" +msgstr[0] "致盲闪光卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Ethereal Grasp" msgid_plural "Scrolls of Ethereal Grasp" -msgstr[0] "" +msgstr[0] "幽影攫抓卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Aura of Protection" msgid_plural "Scrolls of Aura of Protection" -msgstr[0] "" +msgstr[0] "保护光环卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Vegetative Grasp" msgid_plural "Scrolls of Vegetative Grasp" -msgstr[0] "" +msgstr[0] "藤蔓缠绕卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Root Strike" msgid_plural "Scrolls of Root Strike" -msgstr[0] "" +msgstr[0] "树根穿刺卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Wooden Shaft" msgid_plural "Scrolls of Wooden Shaft" -msgstr[0] "" +msgstr[0] "硬木投掷卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Nature's Bow" msgid_plural "Scrolls of Nature's Bow" -msgstr[0] "" +msgstr[0] "自然之弓卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Nature's Trance" msgid_plural "Scrolls of Nature's Trance" -msgstr[0] "" +msgstr[0] "自然冥想卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Bag of Cats" msgid_plural "Scrolls of Bag of Cats" -msgstr[0] "" +msgstr[0] "袋装猫咪卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Stonefist" msgid_plural "Scrolls of Stonefist" -msgstr[0] "" +msgstr[0] "大地之拳卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Seismic Stomp" msgid_plural "Scrolls of Seismic Stomp" -msgstr[0] "" +msgstr[0] "战争践踏卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Stone's Endurance" msgid_plural "Scrolls of Stone's Endurance" -msgstr[0] "" +msgstr[0] "坚如磐石卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Shardspray" msgid_plural "Scrolls of Shardspray" -msgstr[0] "" +msgstr[0] "碎片喷射卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Piercing Bolt" msgid_plural "Scrolls of Piercing Bolt" -msgstr[0] "" +msgstr[0] "穿刺箭卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Shardstorm" msgid_plural "Scrolls of Shardstorm" -msgstr[0] "" +msgstr[0] "碎片风暴卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Rockbolt" msgid_plural "Scrolls of Rockbolt" -msgstr[0] "" +msgstr[0] "石之箭卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Point Flare" msgid_plural "Scrolls of Point Flare" -msgstr[0] "" +msgstr[0] "定点炎爆卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Finger Firelighter" msgid_plural "Scrolls of Finger Firelighter" -msgstr[0] "" +msgstr[0] "火焰之指卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Ice Spike" msgid_plural "Scrolls of Ice Spike" -msgstr[0] "" +msgstr[0] "冰刺卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Fireball" msgid_plural "Scrolls of Fireball" -msgstr[0] "" +msgstr[0] "火球术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Cone of Cold" msgid_plural "Scrolls of Cone of Cold" -msgstr[0] "" +msgstr[0] "极寒喷射卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Burning Hands" msgid_plural "Scrolls of Burning Hands" -msgstr[0] "" +msgstr[0] "燃烧之手卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Frost Spray" msgid_plural "Scrolls of Frost Spray" -msgstr[0] "" +msgstr[0] "寒霜喷射卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Chilling Touch" msgid_plural "Scrolls of Chilling Touch" -msgstr[0] "" +msgstr[0] "寒冷之触卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Glide on Ice" msgid_plural "Scrolls of Glide on Ice" -msgstr[0] "" +msgstr[0] "冰上滑行卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Hoary Blast" msgid_plural "Scrolls of Hoary Blast" -msgstr[0] "" +msgstr[0] "白霜冲击卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Ice Shield" msgid_plural "Scrolls of Ice Shield" -msgstr[0] "" +msgstr[0] "冰盾卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Frost Armor" msgid_plural "Scrolls of Frost Armor" -msgstr[0] "" +msgstr[0] "霜甲卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Magic Missile" msgid_plural "Scrolls of Magic Missile" -msgstr[0] "" +msgstr[0] "魔法飞弹卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Phase Door" msgid_plural "Scrolls of Phase Door" -msgstr[0] "" +msgstr[0] "相位门卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Gravity Well" msgid_plural "Scrolls of Gravity Well" -msgstr[0] "" +msgstr[0] "重力井卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Mana Blast" msgid_plural "Scrolls of Mana Blast" -msgstr[0] "" +msgstr[0] "奥术冲击卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Mana Bolt" msgid_plural "Scrolls of Mana Bolt" -msgstr[0] "" +msgstr[0] "奥术闪电卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Haste" msgid_plural "Scrolls of Haste" -msgstr[0] "" +msgstr[0] "加速术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Mana Beam" msgid_plural "Scrolls of Mana Beam" -msgstr[0] "" +msgstr[0] "奥术光束卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Escape" msgid_plural "Scrolls of Escape" -msgstr[0] "" +msgstr[0] "逃脱术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Cat's Grace" msgid_plural "Scrolls of Cat's Grace" -msgstr[0] "" +msgstr[0] "猫之优雅卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Eagle's Sight" msgid_plural "Scrolls of Eagle's Sight" -msgstr[0] "" +msgstr[0] "鹰眼卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Ogre's Strength" msgid_plural "Scrolls of Ogre's Strength" -msgstr[0] "" +msgstr[0] "巨魔之力卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Fox's Cunning" msgid_plural "Scrolls of Fox's Cunning" -msgstr[0] "" +msgstr[0] "狐之狡黠卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Jolt" msgid_plural "Scrolls of Jolt" -msgstr[0] "" +msgstr[0] "震颤电击卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Lightning Bolt" msgid_plural "Scrolls of Lightning Bolt" -msgstr[0] "" +msgstr[0] "闪电束卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Windstrike" msgid_plural "Scrolls of Windstrike" -msgstr[0] "" +msgstr[0] "风击术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Windrunning" msgid_plural "Scrolls of Windrunning" -msgstr[0] "" +msgstr[0] "风行术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Call Stormhammer" msgid_plural "Scrolls of Call Stormhammer" -msgstr[0] "" +msgstr[0] "风暴之锤卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Bless" msgid_plural "Scrolls of Bless" -msgstr[0] "" +msgstr[0] "祝福卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Holy Blade" msgid_plural "Scrolls of Holy Blade" -msgstr[0] "" +msgstr[0] "光明之刃卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Spiritual Armor" msgid_plural "Scrolls of Spiritual Armor" -msgstr[0] "" +msgstr[0] "心灵装甲卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Lamp" msgid_plural "Scrolls of Lamp" -msgstr[0] "" +msgstr[0] "魔法灯卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Manatricity" msgid_plural "Scrolls of Manatricity" -msgstr[0] "" +msgstr[0] "魔能转换术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Taze" msgid_plural "Scrolls of Taze" -msgstr[0] "" +msgstr[0] "电击术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Lesser Quantum Tunnel" msgid_plural "Scrolls of Lesser Quantum Tunnel" -msgstr[0] "" +msgstr[0] "次级隧穿术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Synaptic Stimulation" msgid_plural "Scrolls of Synaptic Stimulation" -msgstr[0] "" +msgstr[0] "突触刺激卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Laze" msgid_plural "Scrolls of Laze" -msgstr[0] "" +msgstr[0] "激光术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Animated Blade" msgid_plural "Scrolls of Animated Blade" -msgstr[0] "" +msgstr[0] "魔剑苏生卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Mirror Image" msgid_plural "Scrolls of Mirror Image" -msgstr[0] "" +msgstr[0] "召唤镜像卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Lightning Blast" msgid_plural "Scrolls of Lightning Blast" -msgstr[0] "" +msgstr[0] "闪电冲击卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Necrotic Gaze" msgid_plural "Scrolls of Necrotic Gaze" -msgstr[0] "" +msgstr[0] "死灵凝视卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Purification Seed" msgid_plural "Scrolls of Purification Seed" -msgstr[0] "" +msgstr[0] "净化之种卷轴" #. ~ Description for {'str': 'Scroll of Purification Seed', 'str_pl': 'Scrolls #. of Purification Seed'} @@ -197732,7 +198114,7 @@ msgstr "你召喚大地的贈禮,它將淨化水質。越高的等級能產生 #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Optical Sneeze Beam" msgid_plural "Scrolls of Optical Sneeze Beam" -msgstr[0] "" +msgstr[0] "喷嚏激光术卷轴" #. ~ Description for {'str': 'Scroll of Optical Sneeze Beam', 'str_pl': #. 'Scrolls of Optical Sneeze Beam'} @@ -197745,12 +198127,12 @@ msgstr "你将体内的生化电池过载,从你的脸上射出半定向的激 #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Lava Bomb" msgid_plural "Scrolls of Lava Bomb" -msgstr[0] "" +msgstr[0] "熔岩炸弹卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Acid Resistance" msgid_plural "Scrolls of Acid Resistance" -msgstr[0] "" +msgstr[0] "防酸术卷轴" #. ~ Description for {'str': 'Scroll of Acid Resistance', 'str_pl': 'Scrolls #. of Acid Resistance'} @@ -197761,7 +198143,7 @@ msgstr "这法术能产生一个肉眼无法看见的防酸光环保护你。" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Lightning Storm" msgid_plural "Scrolls of Lightning Storm" -msgstr[0] "" +msgstr[0] "闪电雷暴卷轴" #. ~ Description for {'str': 'Scroll of Lightning Storm', 'str_pl': 'Scrolls #. of Lightning Storm'} @@ -197775,57 +198157,57 @@ msgstr "這卷軸詳細描述了如何耗用更多的法力來改變塑風者常 #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Sacrificial Regrowth" msgid_plural "Scrolls of Sacrificial Regrowth" -msgstr[0] "" +msgstr[0] "沃血重萌卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Sacrificial Healing" msgid_plural "Scrolls of Sacrificial Healing" -msgstr[0] "" +msgstr[0] "舍己济人卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Stoneskin" msgid_plural "Scrolls of Stoneskin" -msgstr[0] "" +msgstr[0] "石肤术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Pillar of Stone" msgid_plural "Scrolls of Pillar of Stone" -msgstr[0] "" +msgstr[0] "石柱术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Paralytic Dart" msgid_plural "Scrolls of Paralytic Dart" -msgstr[0] "" +msgstr[0] "麻痹毒刺卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Visceral Projection" msgid_plural "Scrolls of Visceral Projection" -msgstr[0] "" +msgstr[0] "脏腑四射卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Coagulant Weave" msgid_plural "Scrolls of Coagulant Weave" -msgstr[0] "" +msgstr[0] "凝结组织卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Ionization" msgid_plural "Scrolls of Ionization" -msgstr[0] "" +msgstr[0] "电离术卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Ignus Fatuus" msgid_plural "Scrolls of Ignus Fatuus" -msgstr[0] "" +msgstr[0] "召唤鬼火卷轴" #: data/mods/Magiclysm/items/spell_scrolls.json msgid "Scroll of Wall of Fog" msgid_plural "Scrolls of Wall of Fog" -msgstr[0] "" +msgstr[0] "雾墙术卷轴" #: data/mods/Magiclysm/items/spellbooks.json msgid "A Technomancer's Guide to Debugging C:DDA" msgid_plural "copies of A Technomancer's Guide to Debugging C:DDA" -msgstr[0] "" +msgstr[0] "科技法师的CDDA调试指南" #. ~ Description for {'str': "A Technomancer's Guide to Debugging C:DDA", #. 'str_pl': "copies of A Technomancer's Guide to Debugging C:DDA"} @@ -197836,7 +198218,7 @@ msgstr "static std::string 描述(法術 sp)const;" #: data/mods/Magiclysm/items/spellbooks.json msgid "A Beginner's Guide to Magic" msgid_plural "copies of A Beginner's Guide to Magic" -msgstr[0] "" +msgstr[0] "魔法入门指南" #. ~ Description for {'str': "A Beginner's Guide to Magic", 'str_pl': "copies #. of A Beginner's Guide to Magic"} @@ -197849,7 +198231,7 @@ msgstr "比起法術書,你覺得它被稱為一本小冊子會更適當。但 #: data/mods/Magiclysm/items/spellbooks.json msgid "Wizarding Guide to Backpacking" msgid_plural "copies of Wizarding Guide to Backpacking" -msgstr[0] "" +msgstr[0] "魔法师背包指南" #. ~ Description for {'str': 'Wizarding Guide to Backpacking', 'str_pl': #. 'copies of Wizarding Guide to Backpacking'} @@ -197863,7 +198245,7 @@ msgstr "這似乎是背包旅行指南的法術版本,教導你該打包何物 #: data/mods/Magiclysm/items/spellbooks.json msgid "Pyromancy for Heretics" msgid_plural "copies of Pyromancy for Heretics" -msgstr[0] "" +msgstr[0] "异教徒的火焰魔法" #. ~ Description for {'str': 'Pyromancy for Heretics', 'str_pl': 'copies of #. Pyromancy for Heretics'} @@ -197875,7 +198257,7 @@ msgstr "這本書雖然有著燒焦的書皮,卻仍然記述著許多點燃物 #: data/mods/Magiclysm/items/spellbooks.json msgid "A Treatise on Magical Elements" msgid_plural "copies of A Treatise on Magical Elements" -msgstr[0] "" +msgstr[0] "魔法元素论" #. ~ Description for {'str': 'A Treatise on Magical Elements', 'str_pl': #. 'copies of A Treatise on Magical Elements'} @@ -197888,7 +198270,7 @@ msgstr "這本書以詳細而複雜圖表、儀式和動作順序來介紹各種 #: data/mods/Magiclysm/items/spellbooks.json msgid "Introduction to the Divine" msgid_plural "copies of Introduction to the Divine" -msgstr[0] "" +msgstr[0] "神祇简介" #. ~ Description for {'str': 'Introduction to the Divine', 'str_pl': 'copies #. of Introduction to the Divine'} @@ -197901,7 +198283,7 @@ msgstr "這似乎主要是宗教文本,但它確實有一些關於治療的記 #: data/mods/Magiclysm/items/spellbooks.json msgid "The Paladin's Guide to Modern Spellcasting" msgid_plural "copies of The Paladin's Guide to Modern Spellcasting" -msgstr[0] "" +msgstr[0] "圣骑士的现代施法指南" #. ~ Description for {'str': "The Paladin's Guide to Modern Spellcasting", #. 'str_pl': "copies of The Paladin's Guide to Modern Spellcasting"} @@ -197914,7 +198296,7 @@ msgstr "雖說書名這麼寫,但是內容卻是用中古世紀的英文寫成 #: data/mods/Magiclysm/items/spellbooks.json msgid "Winter's Eternal Grasp" msgid_plural "copies of Winter's Eternal Grasp" -msgstr[0] "" +msgstr[0] "寒冬之悟" #. ~ Description for {'str': "Winter's Eternal Grasp", 'str_pl': "copies of #. Winter's Eternal Grasp"} @@ -197926,7 +198308,7 @@ msgstr "這本小冊子似乎是冰製的,摸起來很冰冷。" #: data/mods/Magiclysm/items/spellbooks.json msgid "The Tome of The Oncoming Storm" msgid_plural "copies of The Tome of The Oncoming Storm" -msgstr[0] "" +msgstr[0] "风暴来临法典" #. ~ Description for {'str': 'The Tome of The Oncoming Storm', 'str_pl': #. 'copies of The Tome of The Oncoming Storm'} @@ -197939,7 +198321,7 @@ msgstr "封面浮飾著交叉閃電與暴雨雲圖樣的大部頭書。觸摸著 #: data/mods/Magiclysm/items/spellbooks.json msgid "Nondescript Spellbook" msgid_plural "copies of Nondescript Spellbook" -msgstr[0] "" +msgstr[0] "普通的魔法书" #. ~ Description for {'str': 'Nondescript Spellbook', 'str_pl': 'copies of #. Nondescript Spellbook'} @@ -197950,7 +198332,7 @@ msgstr "一本小書,記述著由新手魔法師創造的法術。" #: data/mods/Magiclysm/items/spellbooks.json msgid "Of Light and Falsehoods" msgid_plural "copies of Of Light and Falsehoods" -msgstr[0] "" +msgstr[0] "光影和幻象" #. ~ Description for {'str': 'Of Light and Falsehoods', 'str_pl': 'copies of #. Of Light and Falsehoods'} @@ -197961,7 +198343,7 @@ msgstr "一本白色小册子,它淡淡地增强了四周的光。" #: data/mods/Magiclysm/items/spellbooks.json msgid "The Tome of Flesh" msgid_plural "copies of The Tome of Flesh" -msgstr[0] "" +msgstr[0] "血肉之书" #. ~ Description for {'str': 'The Tome of Flesh', 'str_pl': 'copies of The #. Tome of Flesh'} @@ -197972,7 +198354,7 @@ msgstr "一本小專論,封面似乎是鞣製後的人皮。" #: data/mods/Magiclysm/items/spellbooks.json msgid "The Book of Trees" msgid_plural "copies of The Book of Trees" -msgstr[0] "" +msgstr[0] "树之书" #. ~ Description for {'str': 'The Book of Trees', 'str_pl': 'copies of The #. Book of Trees'} @@ -197983,7 +198365,7 @@ msgstr "有著樹皮封面的書。" #: data/mods/Magiclysm/items/spellbooks.json msgid "The Utility of Mana as an Energy Source" msgid_plural "copies of The Utility of Mana as an Energy Source" -msgstr[0] "" +msgstr[0] "魔力能源的效用" #. ~ Description for {'str': 'The Utility of Mana as an Energy Source', #. 'str_pl': 'copies of The Utility of Mana as an Energy Source'} @@ -197996,7 +198378,7 @@ msgstr "本書詳細介紹了使用你的法力來恢復各種生理效果的法 #: data/mods/Magiclysm/items/spellbooks.json msgid "The Tome of The Battle Mage" msgid_plural "copies of The Tome of The Battle Mage" -msgstr[0] "" +msgstr[0] "战斗法师宝典" #. ~ Description for {'str': 'The Tome of The Battle Mage', 'str_pl': 'copies #. of The Tome of The Battle Mage'} @@ -198009,7 +198391,7 @@ msgstr "以你的法師標準來看此書,內容滿是祆教徒的戰鬥法術 #: data/mods/Magiclysm/items/spellbooks.json msgid "The Tome of the Hollow Earth" msgid_plural "copies of The Tome of the Hollow Earth" -msgstr[0] "" +msgstr[0] "地心空洞论" #. ~ Description for {'str': 'The Tome of the Hollow Earth', 'str_pl': 'copies #. of The Tome of the Hollow Earth'} @@ -198022,7 +198404,7 @@ msgstr "這本佈滿沙塵的大部頭書似乎永遠都佈滿著灰塵。它記 #: data/mods/Magiclysm/items/spellbooks.json msgid "The Tome of Magical Movement" msgid_plural "copies of The Tome of Magical Movement" -msgstr[0] "" +msgstr[0] "魔法移动宝典" #. ~ Description for {'str': 'The Tome of Magical Movement', 'str_pl': 'copies #. of The Tome of Magical Movement'} @@ -198049,7 +198431,7 @@ msgstr "這看起來像是有人正在設計一個新的法術,卻在上面灑 #: data/mods/Magiclysm/items/spellbooks.json msgid "Necromantic Minions for Dummies" msgid_plural "copies of Necromantic Minions for Dummies" -msgstr[0] "" +msgstr[0] "亡灵仆从召唤入门" #. ~ Description for {'str': 'Necromantic Minions for Dummies', 'str_pl': #. 'copies of Necromantic Minions for Dummies'} @@ -198062,7 +198444,7 @@ msgstr "這本書詳細介紹了召喚不死小兵為你作戰的各種方法。 #: data/mods/Magiclysm/items/spellbooks.json msgid "Fundamentals of Technomancy" msgid_plural "copies of Fundamentals of Technomancy" -msgstr[0] "" +msgstr[0] "科技魔法基本原理" #. ~ Description for {'str': 'Fundamentals of Technomancy', 'str_pl': 'copies #. of Fundamentals of Technomancy'} @@ -198075,7 +198457,7 @@ msgstr "這本厚厚的說明書指導施法者如何操縱和賦予各種形式 #: data/mods/Magiclysm/items/spellbooks.json msgid "Complete Idiot's Guide to Technomancy" msgid_plural "copies of Complete Idiot's Guide to Technomancy" -msgstr[0] "" +msgstr[0] "科技魔法新手入门指南" #. ~ Description for {'str': "Complete Idiot's Guide to Technomancy", #. 'str_pl': "copies of Complete Idiot's Guide to Technomancy"} @@ -198088,7 +198470,7 @@ msgstr "這個色彩繽紛的指南,充滿了圖表和漫畫,教授給不那 #: data/mods/Magiclysm/items/spellbooks.json msgid "Technomancy and the Electromagnetic Spectrum" msgid_plural "copies of Technomancy and the Electromagnetic Spectrum" -msgstr[0] "" +msgstr[0] "科技魔法与电磁光谱" #. ~ Description for {'str': 'Technomancy and the Electromagnetic Spectrum', #. 'str_pl': 'copies of Technomancy and the Electromagnetic Spectrum'} @@ -198101,7 +198483,7 @@ msgstr "這本實驗室參考資料書很厚,內含關於魔法與電磁輻射 #: data/mods/Magiclysm/items/spellbooks.json msgid "Geospatial Systems: The Lie Of Linearity" msgid_plural "copies of Geospatial Systems: The Lie Of Linearity" -msgstr[0] "" +msgstr[0] "空间与地理:线性的谎言" #. ~ Description for {'str': 'Geospatial Systems: The Lie Of Linearity', #. 'str_pl': 'copies of Geospatial Systems: The Lie Of Linearity'} @@ -198118,7 +198500,7 @@ msgstr "" #: data/mods/Magiclysm/items/spellbooks.json msgid "Transcendence of the Human Condition" msgid_plural "copies of Transcendence of the Human Condition" -msgstr[0] "" +msgstr[0] "超越人类的极限" #. ~ Description for {'str': 'Transcendence of the Human Condition', 'str_pl': #. 'copies of Transcendence of the Human Condition'} @@ -198132,7 +198514,7 @@ msgstr "人類是唯一尋求改善自己的生物。本研究考察了可以暫 #: data/mods/Magiclysm/items/tools.json msgid "cauldron of purification" msgid_plural "cauldrons of purification" -msgstr[0] "" +msgstr[0] "净化大锅" #. ~ Description for {'str': 'cauldron of purification', 'str_pl': 'cauldrons #. of purification'} @@ -198154,7 +198536,7 @@ msgstr "一个便携式版本的火炭锻造台,它使用了恶魔蜘蛛甲壳 #: data/mods/Magiclysm/items/tools.json msgid "fireproof mortar" msgid_plural "fireproof mortar" -msgstr[0] "" +msgstr[0] "防火灰泥" #. ~ Description for {'str_sp': 'fireproof mortar'} #: data/mods/Magiclysm/items/tools.json @@ -198170,7 +198552,7 @@ msgstr "鯊蜥獸甲裝甲板" #: data/mods/Magiclysm/items/weapons.json msgid "greatclub" msgid_plural "greatclubs" -msgstr[0] "" +msgstr[0] "巨木棒" #. ~ Description for greatclub #: data/mods/Magiclysm/items/weapons.json @@ -198182,7 +198564,7 @@ msgstr "一根顶端有个十分粗壮疙瘩的坚固木棍。虽然它很重, #: data/mods/Magiclysm/items/weapons.json msgid "wood trident" msgid_plural "wood tridents" -msgstr[0] "" +msgstr[0] "木制三叉戟" #. ~ Description for wood trident #: data/mods/Magiclysm/items/weapons.json @@ -198196,7 +198578,7 @@ msgstr "" #: data/mods/Magiclysm/items/weapons.json msgid "barbed javelin" msgid_plural "barbed javelins" -msgstr[0] "" +msgstr[0] "带刺标枪" #. ~ Description for {'str': 'barbed javelin'} #: data/mods/Magiclysm/items/weapons.json @@ -198214,7 +198596,7 @@ msgstr "射出带刺标枪的假枪。" #: data/mods/Magiclysm/vehicleparts/frames.json msgid "foldable orichalcum frame" msgid_plural "foldable orichalcum frames" -msgstr[0] "" +msgstr[0] "折叠山铜车架" #. ~ Description for foldable orichalcum frame #: data/mods/Magiclysm/items/vehicle/frames.json @@ -198227,7 +198609,7 @@ msgstr "一种由山铜管制成的折叠框架。不像铝那么轻,但非常 #: data/mods/Magiclysm/vehicleparts/frames.json msgid "orichalcum frame" msgid_plural "orichalcum frames" -msgstr[0] "" +msgstr[0] "山铜车架" #. ~ Description for orichalcum frame #: data/mods/Magiclysm/items/vehicle/frames.json @@ -198236,6 +198618,11 @@ msgid "" "much more expensive." msgstr "一个由山铜制成的车架。比钢制车架要坚固得多,但同时也比它昂贵得多。" +#: data/mods/Magiclysm/monsters/demon_spider.json +msgid "demon spider" +msgid_plural "demon spiders" +msgstr[0] "惡魔蜘蛛" + #: data/mods/Magiclysm/monsters/demon_spider.json msgid "demon spiderling" msgid_plural "demon spiderlings" @@ -198251,11 +198638,6 @@ msgid "" msgstr "" "雖然牠已經有小狗大小的體型,但你仍然知道這只是非常幼小的惡魔蜘蛛。牠的血腥的紅色就是你稱牠惡魔的原因。在大災變之前你根本沒見過這種生物。牠行動快速,而且有正滴著毒液的大毒牙。" -#: data/mods/Magiclysm/monsters/demon_spider.json -msgid "demon spider" -msgid_plural "demon spiders" -msgstr[0] "惡魔蜘蛛" - #. ~ Description for demon spider #: data/mods/Magiclysm/monsters/demon_spider.json msgid "" @@ -198339,7 +198721,7 @@ msgstr "身披黑色鱗片的怪獸,在那深深的眼窩中有著泛邪惡的 #: data/mods/Magiclysm/monsters/golems.json msgid "clay golem" msgid_plural "clay golems" -msgstr[0] "" +msgstr[0] "粘土傀儡" #. ~ Description for clay golem #: data/mods/Magiclysm/monsters/golems.json @@ -198351,7 +198733,7 @@ msgstr "一个用粘土制成的巨大人型傀儡,它的比例不协调,看 #: data/mods/Magiclysm/monsters/golems.json msgid "plastic golem" msgid_plural "plastic golems" -msgstr[0] "" +msgstr[0] "塑料傀儡" #. ~ Description for {'str': 'plastic golem'} #: data/mods/Magiclysm/monsters/golems.json @@ -198366,7 +198748,7 @@ msgstr "" #: data/mods/Magiclysm/monsters/golems.json msgid "stone golem" msgid_plural "stone golems" -msgstr[0] "" +msgstr[0] "石傀儡" #. ~ Description for stone golem #: data/mods/Magiclysm/monsters/golems.json @@ -198377,7 +198759,7 @@ msgstr "一个用石头制成的巨大人型傀儡,它的拳头看起来像火 #: data/mods/Magiclysm/monsters/golems.json msgid "iron golem" msgid_plural "iron golems" -msgstr[0] "" +msgstr[0] "铁傀儡" #. ~ Description for iron golem #: data/mods/Magiclysm/monsters/golems.json @@ -198389,7 +198771,7 @@ msgstr "一个用铁制成的巨大人型傀儡,某种有毒气体从嘴里渗 #: data/mods/Magiclysm/monsters/lizardfolk.json msgid "lizardfolk warrior" msgid_plural "lizardfolk warriors" -msgstr[0] "" +msgstr[0] "蜥蜴人战士" #. ~ Description for lizardfolk warrior #: data/mods/Magiclysm/monsters/lizardfolk.json @@ -198407,7 +198789,7 @@ msgstr "" #: data/mods/Magiclysm/monsters/lizardfolk.json msgid "lizardfolk hunter" msgid_plural "lizardfolk hunters" -msgstr[0] "" +msgstr[0] "蜥蜴人猎手" #. ~ Description for lizardfolk hunter #: data/mods/Magiclysm/monsters/lizardfolk.json @@ -198423,7 +198805,7 @@ msgstr "蜥蜴人猎手向你掷出一根带刺标枪!" #: data/mods/Magiclysm/monsters/lizardfolk.json msgid "lizardfolk shaman" msgid_plural "lizardfolk shamans" -msgstr[0] "" +msgstr[0] "蜥蜴人萨满" #. ~ Description for lizardfolk shaman #: data/mods/Magiclysm/monsters/lizardfolk.json @@ -198440,7 +198822,7 @@ msgstr "" #: data/mods/Magiclysm/monsters/lizardfolk.json msgid "lizardfolk chieftan" msgid_plural "lizardfolk chieftans" -msgstr[0] "" +msgstr[0] "蜥蜴人酋长" #. ~ Description for lizardfolk chieftan #: data/mods/Magiclysm/monsters/lizardfolk.json @@ -198456,7 +198838,7 @@ msgstr "" #: data/mods/Magiclysm/monsters/lizardfolk.json msgid "crocodile" msgid_plural "crocodiles" -msgstr[0] "" +msgstr[0] "鳄鱼" #. ~ Description for crocodile #: data/mods/Magiclysm/monsters/lizardfolk.json @@ -198502,7 +198884,7 @@ msgstr "黑布丁怪喷出酸液灼烧 %3$s !" #: data/mods/Magiclysm/monsters/monsters.json msgid "krabgek" msgid_plural "krabgeks" -msgstr[0] "" +msgstr[0] "魔眼怪" #. ~ Description for krabgek #: data/mods/Magiclysm/monsters/monsters.json @@ -198569,7 +198951,7 @@ msgstr "一只体型庞大的绿色皮肤的类人生物。巨魔以其厚皮和 #: data/mods/Magiclysm/monsters/monsters.json msgid "stirge" msgid_plural "stirges" -msgstr[0] "" +msgstr[0] "蚊蝠" #. ~ Description for stirge #: data/mods/Magiclysm/monsters/monsters.json @@ -198581,7 +198963,7 @@ msgstr "这只可怕的飞行生物看起来就像一只大蝙蝠和一只超大 #: data/mods/Magiclysm/monsters/monsters.json msgid "shrieker" msgid_plural "shriekers" -msgstr[0] "" +msgstr[0] "尖叫蘑菇怪" #. ~ Description for shrieker #: data/mods/Magiclysm/monsters/monsters.json @@ -198593,7 +198975,7 @@ msgstr "尖叫蘑菇怪是一种和人一样大的蘑菇,通过发出刺耳的 #: data/mods/Magiclysm/monsters/monsters.json msgid "lemure" msgid_plural "lemures" -msgstr[0] "" +msgstr[0] "劣魔" #. ~ Description for lemure #: data/mods/Magiclysm/monsters/monsters.json @@ -199352,7 +199734,7 @@ msgstr "飘浮碟" #: data/mods/Magiclysm/vehicles/summoned_vehicles.json msgid "mana wheel" msgid_plural "mana wheels" -msgstr[0] "" +msgstr[0] "魔法车轮" #. ~ Description for mana wheel #: data/mods/Magiclysm/vehicles/summoned_vehicles.json @@ -199375,7 +199757,7 @@ msgstr "魔力" #: data/mods/Magiclysm/vehicles/summoned_vehicles.json msgid "mana core power" msgid_plural "mana core powers" -msgstr[0] "" +msgstr[0] "魔力动力" #. ~ Description for mana core power #: data/mods/Magiclysm/vehicles/summoned_vehicles.json @@ -199891,7 +200273,7 @@ msgstr[0] "內置電磁脈衝發射器" #: data/mods/Modular_Turrets/items.json data/mods/Modular_Turrets/monster.json msgid "disarmed defense turret" msgid_plural "disarmed defense turrets" -msgstr[0] "" +msgstr[0] "防御炮塔(无武装)" #. ~ Description for disarmed defense turret #: data/mods/Modular_Turrets/items.json @@ -200342,7 +200724,7 @@ msgstr "" #: data/mods/Modular_Turrets/monster.json msgid "needle turret" msgid_plural "needle turrets" -msgstr[0] "" +msgstr[0] "镖形弹炮塔" #. ~ Description for needle turret #: data/mods/Modular_Turrets/monster.json @@ -200548,7 +200930,7 @@ msgstr[0] "內置雷射器" #: data/mods/Modular_Turrets/roboguns.json msgid "integral lightning caster" msgid_plural "integral lightning casters" -msgstr[0] "" +msgstr[0] "内置放电装置" #: data/mods/Modular_Turrets/roboguns.json msgid "integral EMP generator" @@ -200581,7 +200963,7 @@ msgstr "" #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json msgid "necco corpse" msgid_plural "necco corpses" -msgstr[0] "" +msgstr[0] "糖猫尸体" #. ~ Description for necco corpse #: data/mods/My_Sweet_Cataclysm/sweet_comestibles.json @@ -200680,7 +201062,7 @@ msgstr "厚口香糖网" #: data/mods/My_Sweet_Cataclysm/sweet_items.json msgid "SugarKin flyer" msgid_plural "SugarKin flyers" -msgstr[0] "" +msgstr[0] "糖人传单" #. ~ Description for {'str': 'SugarKin flyer'} #: data/mods/My_Sweet_Cataclysm/sweet_items.json @@ -200711,7 +201093,7 @@ msgstr "糖" #: data/mods/My_Sweet_Cataclysm/sweet_med.json msgid "caramel ointment" msgid_plural "caramel ointments" -msgstr[0] "" +msgstr[0] "焦糖药膏" #. ~ Description for caramel ointment #: data/mods/My_Sweet_Cataclysm/sweet_med.json @@ -200723,7 +201105,7 @@ msgstr "一份用焦糖制成的药膏。如果你是糖做的人的话,可以 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "necco" msgid_plural "neccos" -msgstr[0] "" +msgstr[0] "糖果猫" #. ~ Description for {'str': 'necco'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200733,7 +201115,7 @@ msgstr "一块巨大的彩虹糖,快乐的跳来跳去。" #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow kid" msgid_plural "marshmallow kids" -msgstr[0] "" +msgstr[0] "棉花糖小子" #. ~ Description for {'str': 'marshmallow kid'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200745,7 +201127,7 @@ msgstr "一只完全由棉花糖组成的小型类人生物。它用粗短软垫 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow guy" msgid_plural "marshmallow guys" -msgstr[0] "" +msgstr[0] "棉花糖人" #. ~ Description for {'str': 'marshmallow guy'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200757,7 +201139,7 @@ msgstr "一只由棉花糖组成的类人生物,脸上勾勒着微笑。它蹒 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow buff" msgid_plural "marshmallow buffs" -msgstr[0] "" +msgstr[0] "棉花糖壮汉" #. ~ Description for {'str': 'marshmallow buff'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200769,7 +201151,7 @@ msgstr "一只体型健壮的由棉花糖组成的类人生物,自豪地迈向 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow goliath" msgid_plural "marshmallow goliaths" -msgstr[0] "" +msgstr[0] "棉花糖巨人" #. ~ Description for {'str': 'marshmallow goliath'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200781,7 +201163,7 @@ msgstr "一只体型巨大的棉花糖类人生物,正轻柔地踏步漫行, #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow squire" msgid_plural "marshmallow squires" -msgstr[0] "" +msgstr[0] "棉花糖扈从" #. ~ Description for {'str': 'marshmallow squire'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200794,7 +201176,7 @@ msgstr "一只完全由棉花糖组成的小型类人生物。它穿着一套由 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow knight" msgid_plural "marshmallow knights" -msgstr[0] "" +msgstr[0] "棉花糖骑士" #. ~ Description for {'str': 'marshmallow knight'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200808,7 +201190,7 @@ msgstr "" #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow champion" msgid_plural "marshmallow champions" -msgstr[0] "" +msgstr[0] "棉花糖捍卫者" #. ~ Description for {'str': 'marshmallow champion'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200820,7 +201202,7 @@ msgstr "一只体型健壮的由棉花糖组成的类人生物,穿着一套闪 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "marshmallow war lord" msgid_plural "marshmallow war lords" -msgstr[0] "" +msgstr[0] "棉花糖战争领主" #. ~ Description for {'str': 'marshmallow war lord'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200834,7 +201216,7 @@ msgstr "" #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "gummy cub" msgid_plural "gummy cubs" -msgstr[0] "" +msgstr[0] "幼年软糖熊" #. ~ Description for {'str': 'gummy cub'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200844,7 +201226,7 @@ msgstr "软糖熊的幼体。一只可爱的小熊,全身完全由软糖构成 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "gummy bear" msgid_plural "gummy bears" -msgstr[0] "" +msgstr[0] "软糖熊" #. ~ Description for {'str': 'gummy bear'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200856,7 +201238,7 @@ msgstr "一只由水果味软糖组成的大熊,其圆滑的体形和散发出 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "cracker kid" msgid_plural "cracker kids" -msgstr[0] "" +msgstr[0] "薄脆饼小子" #. ~ Description for {'str': 'cracker kid'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200876,7 +201258,7 @@ msgstr "一块小曲奇饼,正在四处寻找面包屑。" #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "gum spider" msgid_plural "gum spiders" -msgstr[0] "" +msgstr[0] "口香糖蜘蛛" #. ~ Description for {'str': 'gum spider'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -200888,7 +201270,7 @@ msgstr "一块体型巨大的被扯成蜘蛛形状的口香糖。它正静静地 #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json msgid "caffeinated gum spider" msgid_plural "caffeinated gum spiders" -msgstr[0] "" +msgstr[0] "咖啡因口香糖蜘蛛" #. ~ Description for {'str': 'caffeinated gum spider'} #: data/mods/My_Sweet_Cataclysm/sweet_monsters.json @@ -201010,10 +201392,20 @@ msgstr "" "一张介绍某种糖果的传单。上面画着一个用光滑的糖果做成的闪闪发光的人,正害怕地看着你。\"糖人,世上首个真人大小的糖果!你真是个怪物吗?你能把它吞下吗?\"" " " +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "marshmallow" +msgid_plural "marshmallows" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "shlop." msgstr "唰啦。" +#: data/mods/My_Sweet_Cataclysm/sweet_species.json +msgid "gummy" +msgid_plural "gummies" +msgstr[0] "" + #: data/mods/My_Sweet_Cataclysm/sweet_species.json msgid "pop." msgstr "啵。" @@ -201175,7 +201567,7 @@ msgstr "TX-5LR \"地狱犬\"型激光炮塔是其前身的升级版。它的特 #: data/mods/No_Hope/monsters.json msgid "turret" msgid_plural "turrets" -msgstr[0] "" +msgstr[0] "炮塔" #. ~ Description for {'str': 'turret'} #: data/mods/No_Hope/monsters.json @@ -201192,7 +201584,7 @@ msgstr "" #: data/mods/No_Hope/monsters.json msgid "antimateriel turret" msgid_plural "antimateriel turrets" -msgstr[0] "" +msgstr[0] "反器材炮塔" #. ~ Description for {'str': 'antimateriel turret'} #: data/mods/No_Hope/monsters.json @@ -201208,7 +201600,7 @@ msgstr "" #: data/mods/No_Hope/monsters.json msgid "milspec turret" msgid_plural "milspec turrets" -msgstr[0] "" +msgstr[0] "军用炮塔" #. ~ Description for {'str': 'milspec turret'} #: data/mods/No_Hope/monsters.json @@ -201222,7 +201614,7 @@ msgstr "" #: data/mods/No_Hope/monsters.json msgid "security bot" msgid_plural "security bots" -msgstr[0] "" +msgstr[0] "安防机器人" #. ~ Description for {'str': 'security bot'} #: data/mods/No_Hope/monsters.json @@ -201500,7 +201892,7 @@ msgstr "" #: data/mods/No_Hope/Items/armor.json msgid "field combat exoskeleton (on)" msgid_plural "field combat exoskeletons (on)" -msgstr[0] "" +msgstr[0] "战地作战用外骨骼(开)" #. ~ Description for {'str': 'field combat exoskeleton (on)', 'str_pl': 'field #. combat exoskeletons (on)'} @@ -202601,7 +202993,7 @@ msgstr "非洲草原象,一种巨大的陆地动物,嘴里伸出两条长长 #: data/mods/desert_region/desert_monsters.json msgid "hook kangaroo" msgid_plural "hook kangaroos" -msgstr[0] "" +msgstr[0] "勾爪袋鼠" #. ~ Description for {'str': 'hook kangaroo'} #: data/mods/desert_region/desert_monsters.json @@ -202626,7 +203018,7 @@ msgstr "这是一幅可怕的画面,许多泛脓的伤口出都伸出了卷须 #: data/mods/desert_region/desert_monsters.json msgid "zandcrawler" msgid_plural "zandcrawlers" -msgstr[0] "" +msgstr[0] "沙漠爬行者" #. ~ Description for {'str': 'zandcrawler'} #: data/mods/desert_region/desert_monsters.json @@ -203307,6 +203699,15 @@ msgid "" "city size set to 1 and spacing set to 8." msgstr "在乡间玩耍:只有农场、森林和村庄。建议城市大小设置为1,间距设置为8。" +#: data/mods/saveload_lua_test/modinfo.json +msgid "SaveLoad Lua Test" +msgstr "Lua SaveLoad 测试" + +#. ~ Description for SaveLoad Lua Test +#: data/mods/saveload_lua_test/modinfo.json +msgid "Mod for testing Lua save/load API." +msgstr "用于测试Lua保存/加载API的模组。" + #: data/mods/sees_player_hitbutton/modinfo.json msgid "sees-player icon, HitButton_iso" msgstr "发现玩家图标,HitButton_iso版" @@ -203329,6 +203730,77 @@ msgid "" "retrodays tileset." msgstr "如果某个生物发现了你,会显示一个!图标。专为 retrodays 贴图包设计。" +#: data/mods/smart_house_remotes/item.json +msgid "smart house remote" +msgid_plural "smart house remotes" +msgstr[0] "" + +#. ~ Description for {'str': 'smart house remote'} +#: data/mods/smart_house_remotes/item.json +msgid "" +"A small remote with lcd display used to control garage doors and window " +"curtains. Completely useless now, unless you manage to restore power to the" +" house." +msgstr "" + +#: data/mods/smart_house_remotes/iuse.json +msgid "Control doors and shutters" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Open curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Close curtains" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Raise garage door" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "Lower garage door" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's not enough grid charge. +#: data/mods/smart_house_remotes/main.lua +msgid "Low Current At Endpoint" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when player is too far away from the area. +#: data/mods/smart_house_remotes/main.lua +msgid "No Signal" +msgstr "" + +#. ~ Message on the remote, stylized as calculator led display. +#. Shown when there's nothing to activate. +#: data/mods/smart_house_remotes/main.lua +msgid "No Endpoints Available" +msgstr "" + +#: data/mods/smart_house_remotes/main.lua +msgid "The remote beeps quietly." +msgstr "" + +#. ~ Title of the menu prompting player to select what to activate with the +#. remote. +#. Typically it's doors, garage doors or window curtains. +#: data/mods/smart_house_remotes/main.lua +msgid "Select endpoint" +msgstr "" + +#: data/mods/smart_house_remotes/modinfo.json +msgid "Smart House Remotes" +msgstr "" + +#. ~ Description for Smart House Remotes +#: data/mods/smart_house_remotes/modinfo.json +msgid "Add remotes for controlling garage doors and window curtains." +msgstr "" + #: data/mods/speedydex/modinfo.json msgid "SpeedyDex" msgstr "敏捷影響速度" @@ -204755,6 +205227,14 @@ msgstr "切換除錯模式" msgid "Debug Menu" msgstr "除錯選單" +#: data/raw/keybindings/keybindings.json +msgid "Lua Console" +msgstr "Lua 控制台" + +#: data/raw/keybindings/keybindings.json +msgid "Reload Lua Code" +msgstr "重新加载Lua代码" + #: data/raw/keybindings/keybindings.json msgid "View Scentmap" msgstr "檢視嗅覺地圖" @@ -205310,6 +205790,26 @@ msgstr "" msgid "Add new page" msgstr "" +#: data/raw/keybindings/keybindings.json +msgid "Edit command" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History up" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "History down" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the top" +msgstr "" + +#: data/raw/keybindings/keybindings.json +msgid "Scroll to the bottom" +msgstr "" + #: data/raw/keybindings/messages.json msgid "Toggle wide display" msgstr "" @@ -205468,7 +205968,31 @@ msgstr "設定槍塔瞄準模式" #: src/achievement.cpp #, c-format -msgid "Attain %s skill level of %i (%i/%i)." +msgid "Kill at least %i %s%s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Don't kill even a single %s" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Kill no more than %i %s%s" +msgstr "" + +#: src/achievement.cpp +msgid " (failed)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Attain skill level of %i in %s (%i/%i)" +msgstr "" + +#: src/achievement.cpp +#, c-format +msgid "Stay at or below skill level of %i in %s (%i/%i)" msgstr "" #: src/achievement.cpp @@ -205622,6 +206146,8 @@ msgid "" "\n" "%d out of %d, working on %-20s" msgstr "" +"\n" +"%d个中的%d个,正在处理%-20s。" #: src/activity_actor.cpp msgid "You cause a short circuit!" @@ -205694,7 +206220,7 @@ msgstr "失败机会=%f%%" #: src/activity_handlers.cpp #, c-format msgid "You discover: %s!" -msgstr "" +msgstr "你发现了:%s!" #: src/activity_handlers.cpp #, c-format @@ -211049,6 +211575,30 @@ msgstr "abcdefghijklmnopqrstuvwxyz" msgid "に坂索トし荷測のンおク妙免イロコヤ梅棋厚れ表幌" msgstr "金木水火土子丑寅卯辰巳午未申酉戌亥乾坤震兌坎離巽艮休生傷杜景死驚開" +#: src/catalua_console.cpp +msgid "Press Ctrl+S to run script, press Esc to cancel" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press arrow keys to navigate text input" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to add new line" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Enter to enter/edit command, Esc to quit" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press Up/Down arrows to select from history" +msgstr "" + +#: src/catalua_console.cpp +msgid "Press PgUp/PgDn/Home/End to scroll output window" +msgstr "" + #: src/character.cpp src/debug_menu.cpp src/game.cpp src/iuse.cpp #: src/npctrade.cpp msgid "You" @@ -215933,6 +216483,10 @@ msgstr "資訊 ... " msgid "Change [b]attery charge" msgstr "修改载具电量" +#: src/debug_menu.cpp +msgid "Export [j]son template" +msgstr "" + #: src/debug_menu.cpp msgid "Vehicle…" msgstr "载具…" @@ -216049,6 +216603,10 @@ msgstr "返回主選單" msgid "Player…" msgstr "玩家 ... " +#: src/debug_menu.cpp +msgid "Lua console" +msgstr "Lua 控制台" + #: src/debug_menu.cpp msgid "" "Debug Functions - Manipulate the fabric of reality!\n" @@ -216921,6 +217479,10 @@ msgstr "那裡沒有車輛" msgid "By how much? (in kJ, negative to discharge)" msgstr "增加多少?(单位KJ,负数为减少)" +#: src/debug_menu.cpp +msgid "JSON template written to debug.log" +msgstr "" + #: src/dependency_tree.cpp msgid "Missing Dependency(ies): " msgstr "" @@ -222318,7 +222880,7 @@ msgstr "砍劈" #: src/game_inventory.cpp msgid "BULLET" -msgstr "" +msgstr "子弹" #: src/game_inventory.cpp msgid "ACID" @@ -222807,7 +223369,7 @@ msgstr "你没有任何可供安装的生化插件。" #: src/game_inventory.cpp msgid "COMPLICATION CHANCE" -msgstr "" +msgstr "并发症几率" #: src/game_inventory.cpp msgid "OPERATION DURATION" @@ -227366,13 +227928,13 @@ msgstr "* 当前储存条件 无法 保护该物品不腐烂." msgid "" "* Current storage conditions partially protect this item " "from rot. It will stay fresh at least %s." -msgstr "" +msgstr "* 当前储存条件 部分地 保护此物品免受腐烂。 他至少会保持新鲜 %s。" #: src/item.cpp msgid "" "* Current storage conditions fully protect this item from rot." " It will stay fresh indefinitely." -msgstr "" +msgstr "* 当前储存条件 完全 保护此物品免受腐烂。它将无限期保持新鲜。" #: src/item.cpp msgid "* It seems that deep freezing killed all parasites." @@ -227631,7 +228193,7 @@ msgstr "增加模组位置:" #: src/item.cpp msgid "Used on:" -msgstr "" +msgstr "使用在:" #: src/item.cpp msgid "" @@ -227644,6 +228206,8 @@ msgid "" "\n" " Category: " msgstr "" +"\n" +" 类别: " #: src/item.cpp msgid "Incompatible with mod location: " @@ -229517,7 +230081,7 @@ msgstr "这只 %s 不想要这种食物。" #: src/iuse.cpp #, c-format msgid "Tame which animal with the %s?" -msgstr "" +msgstr "用%s驯服哪种动物?" #: src/iuse.cpp msgid "Are you sure you want to feed a person the dog food?" @@ -229544,6 +230108,11 @@ msgstr "%s 將它從你的手中擊出!" msgid "You try to feed the %s some %s, but it vanishes!" msgstr "你想喂 %s 一些 %s,但它消失了!" +#: src/iuse.cpp +#, c-format +msgid "You reach for the %s, but it recoils away from you!" +msgstr "" + #: src/iuse.cpp msgid "You want to feed it the dog food, but it bites your fingers!" msgstr "你想餵牠狗食, 但牠卻咬了你的手指!" @@ -232483,7 +233052,7 @@ msgstr "下次在食用应当热食的时候,你会尝试使用%s来加热食 #: src/iuse.cpp #, c-format msgid "You will no longer use %s to heat food." -msgstr "" +msgstr "你不会再用%s来加热食物。" #: src/iuse.cpp msgid "This electric grid has no connections." @@ -235422,6 +235991,11 @@ msgstr "" msgid "Create World" msgstr "創造世界" +#. ~ Marker for worlds that need Lua in game builds without Lua +#: src/main_menu.cpp src/worldfactory.cpp +msgid "Needs Lua!" +msgstr "需要Lua!" + #: src/main_menu.cpp msgid "Bugs? Suggestions? Use links in MOTD to report them." msgstr "Bugs? 建議? 請拜訪 \"今日消息\" 頁面裡的網址來回報它們。" @@ -235682,6 +236256,13 @@ msgstr "你確定要刪除 %s 嗎?" msgid "Sorry, something went wrong." msgstr "抱歉, 某處發生錯誤。" +#. ~ Error when attempting to load a world whose mods depend on Lua +#. ~ on game build that doesn't have Lua. %s = world name. +#: src/main_menu.cpp +#, c-format +msgid "%s needs game build with Lua support!" +msgstr "%s 需要支持Lua的游戏版本!" + #. ~ %s = world name #: src/main_menu.cpp #, c-format @@ -235827,7 +236408,7 @@ msgstr " 被掉下的碎片砸到了!" #: src/map.cpp #, c-format msgid "The shot is stopped by the %s!" -msgstr "" +msgstr "这一击被%s挡住了!" #: src/map.cpp msgid "laser beam" @@ -239515,6 +240096,15 @@ msgstr[0] "" msgid "Mod version" msgstr "模組版本" +#: src/mod_manager_ui.cpp +#, c-format +msgid "%s: API version %s\n" +msgstr "" + +#: src/mod_manager_ui.cpp +msgid "Needs Lua" +msgstr "需要Lua" + #: src/mod_manager_ui.cpp msgid "Mod info path" msgstr "modinfo文件路径" @@ -242475,11 +243065,6 @@ msgstr "" msgid "Focus trends towards:" msgstr "專注力趨向:" -#: src/mtype.cpp -msgid "human" -msgid_plural "humans" -msgstr[0] "人類" - #: src/mutation.cpp #, c-format msgid "Your %s is pushed off!" @@ -245125,6 +245710,14 @@ msgstr "" msgid "Messages related to SDL, tiles, tilesets and sound." msgstr "与 SDL、图块、图集和声音有关的信息。" +#: src/options.cpp +msgid "Lua" +msgstr "" + +#: src/options.cpp +msgid "Messages from Lua scripts." +msgstr "来自Lua脚本的訊息。" + #: src/options.cpp msgid "General" msgstr "一般" @@ -246208,6 +246801,16 @@ msgstr "動畫延遲" msgid "The amount of time to pause between animation frames in ms." msgstr "設定每個動畫畫格之間暫停多少毫秒。" +#: src/options.cpp +msgid "Draw bullets as lines" +msgstr "" + +#: src/options.cpp +msgid "" +"If true, bullets are drawn as lines of images, and the animation lasts only " +"one frame." +msgstr "" + #: src/options.cpp msgid "Blinking effects speed" msgstr "闪烁效果速度" @@ -246275,71 +246878,71 @@ msgstr "字體寬度" #: src/options.cpp msgid "Set the font width. Requires restart." -msgstr "" +msgstr "设置字体宽度,需要重新启动。" #: src/options.cpp msgid "Font height" msgstr "字體高度" #: src/options.cpp -msgid "Set the font height. Requires restart." -msgstr "" +msgid "Set the font height. Requires restart." +msgstr "設定字體高度。需要重啟遊戲。" #: src/options.cpp msgid "Font size" msgstr "字體大小" #: src/options.cpp -msgid "Set the font size. Requires restart." -msgstr "" +msgid "Set the font size. Requires restart." +msgstr "設定字體大小。需要重啟遊戲。" #: src/options.cpp msgid "Map font width" msgstr "地圖字體寬度" #: src/options.cpp -msgid "Set the map font width. Requires restart." -msgstr "" +msgid "Set the map font width. Requires restart." +msgstr "設定地圖字體寬度。需要重啟遊戲。" #: src/options.cpp msgid "Map font height" msgstr "地圖字體高度" #: src/options.cpp -msgid "Set the map font height. Requires restart." -msgstr "" +msgid "Set the map font height. Requires restart." +msgstr "設定地圖字體高度。需要重啟遊戲。" #: src/options.cpp msgid "Map font size" msgstr "地圖字體大小" #: src/options.cpp -msgid "Set the map font size. Requires restart." -msgstr "" +msgid "Set the map font size. Requires restart." +msgstr "設定地圖字體大小。需要重啟遊戲。" #: src/options.cpp msgid "Overmap font width" msgstr "世界地圖字體寬度" #: src/options.cpp -msgid "Set the overmap font width. Requires restart." -msgstr "" +msgid "Set the overmap font width. Requires restart." +msgstr "設定世界地圖字體寬度。需要重啟遊戲。" #: src/options.cpp msgid "Overmap font height" msgstr "世界地圖字體高度" #: src/options.cpp -msgid "Set the overmap font height. Requires restart." -msgstr "" +msgid "Set the overmap font height. Requires restart." +msgstr "設定世界地圖字體高度。需要重啟遊戲。" #: src/options.cpp msgid "Overmap font size" msgstr "世界地圖字體大小" #: src/options.cpp -msgid "Set the overmap font size. Requires restart." -msgstr "" +msgid "Set the overmap font size. Requires restart." +msgstr "設定世界地圖字體大小。需要重啟遊戲。" #: src/options.cpp msgid "Enable ASCII art in item descriptions" @@ -253929,6 +254532,11 @@ msgstr "缺失模组" msgid " [%s]" msgstr " [%s]" +#. ~ Tag for mods that use Lua in game builds without Lua. +#: src/worldfactory.cpp +msgid "(Needs Lua) " +msgstr "(需要Lua) " + #: src/worldfactory.cpp msgid "N/A" msgstr "N/A" diff --git a/lang/unicode_check.py b/lang/unicode_check.py index b1759d1a018a..36b616de8c13 100755 --- a/lang/unicode_check.py +++ b/lang/unicode_check.py @@ -7,7 +7,7 @@ def print_encode_error(unicode_err, counter): err_line = counter + chunk.count(b'\n', 0, unicode_err.start) line_start = chunk.rfind(b'\n', 0, unicode_err.start) + 1 line_end = chunk.find(b'\n', line_start) - print("Unicode error on line {0}:".format(err_line)) + print(f"Unicode error on line {err_line}:") # Use RAW write because this is bytes class sys.stdout.buffer.write(chunk[line_start:line_end + 1]) x_num = unicode_err.end - unicode_err.start + 2 @@ -30,7 +30,7 @@ def check(f): if __name__ == '__main__': if len(sys.argv) < 2: - print("Usage: {} [FILENAME]".format(sys.argv[0])) + print(f"Usage: {sys.argv[0]} [FILENAME]") sys.exit(1) with open(sys.argv[1], encoding="utf-8") as pot_file: if not check(pot_file): diff --git a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj index d7ed707f4981..d0a97b76ddf5 100644 --- a/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-lib-vcpkg-static.vcxproj @@ -85,9 +85,9 @@ 4819;4146;26495;26444;26451;4068 stdafx.h /bigobj /utf-8 %(AdditionalOptions) - _SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_CONSOLE;SDL_SOUND;TILES;SDL_BUILDING_LIBRARY;USE_VCPKG;%(PreprocessorDefinitions) + _SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_CONSOLE;SDL_SOUND;TILES;LUA;SDL_BUILDING_LIBRARY;USE_VCPKG;%(PreprocessorDefinitions) stdcpp17 - ..\src;%(AdditionalIncludeDirectories) + ..\src;..\src\lua;%(AdditionalIncludeDirectories) Windows @@ -131,6 +131,16 @@ WIN32;%(PreprocessorDefinitions) + + + NotUsing + + + + NotUsing + + + diff --git a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj index 50284b611de5..758b5d1f02fd 100644 --- a/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-test-vcpkg-static.vcxproj @@ -83,9 +83,9 @@ 4819;4146;26495;26444;26451;4068 stdafx.h /bigobj /utf-8 %(AdditionalOptions) - _SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_CONSOLE;SDL_SOUND;TILES;SDL_MAIN_HANDLED;USE_VCPKG;CATCH_CONFIG_ENABLE_BENCHMARKING;%(PreprocessorDefinitions) + _SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_CONSOLE;SDL_SOUND;TILES;LUA;SDL_MAIN_HANDLED;USE_VCPKG;CATCH_CONFIG_ENABLE_BENCHMARKING;%(PreprocessorDefinitions) stdcpp17 - ..\src;%(AdditionalIncludeDirectories) + ..\src;..\src\lua;%(AdditionalIncludeDirectories) Console diff --git a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj index 08b3ffd8f2bc..a1e5a123317b 100644 --- a/msvc-full-features/Cataclysm-vcpkg-static.vcxproj +++ b/msvc-full-features/Cataclysm-vcpkg-static.vcxproj @@ -102,7 +102,7 @@ 4819;4146;26495;26444;26451;4068 stdafx.h /bigobj /utf-8 %(AdditionalOptions) - _SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WINDOWS;SDL_SOUND;TILES;USE_VCPKG;USE_WINMAIN;%(PreprocessorDefinitions) + _SCL_SECURE_NO_WARNINGS;_CRT_SECURE_NO_WARNINGS;WIN32_LEAN_AND_MEAN;_WINDOWS;SDL_SOUND;TILES;LUA;USE_VCPKG;USE_WINMAIN;%(PreprocessorDefinitions) stdcpp17 diff --git a/src/Android.mk b/src/Android.mk index 466fc2bcd9d5..94ea8eb2a1cc 100644 --- a/src/Android.mk +++ b/src/Android.mk @@ -6,7 +6,7 @@ LOCAL_MODULE := main SDL_PATH := ../SDL2 -LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include +LOCAL_C_INCLUDES := $(LOCAL_PATH)/$(SDL_PATH)/include $(LOCAL_PATH)/lua LOCAL_CPP_FEATURES := exceptions rtti @@ -14,11 +14,14 @@ LOCAL_CPP_FEATURES := exceptions rtti FILE_LIST := $(wildcard $(LOCAL_PATH)/*.cpp) LOCAL_SRC_FILES := $(FILE_LIST:$(LOCAL_PATH)/%=%) +FILE_LIST_LUA := $(wildcard $(LOCAL_PATH)/lua/*.c) +LOCAL_SRC_FILES += $(FILE_LIST_LUA:$(LOCAL_PATH)/%=%) + LOCAL_SHARED_LIBRARIES := libhidapi SDL2 SDL2_mixer SDL2_image SDL2_ttf mpg123 LOCAL_LDLIBS := -lGLESv1_CM -lGLESv2 -llog -LOCAL_CFLAGS += -DTILES=1 -DSDL_SOUND=1 -DCATA_NO_CPP11_STRING_CONVERSIONS=1 -Wextra -Wall -fsigned-char -ffast-math +LOCAL_CFLAGS += -DTILES=1 -DSDL_SOUND=1 -DLUA=1 -DBACKTRACE=1 -Wextra -Wall -fsigned-char -ffast-math LOCAL_LDFLAGS += $(LOCAL_CFLAGS) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 7709f450a93e..0bc909d7624c 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -15,6 +15,14 @@ FILE(GLOB CATACLYSM_BN_HEADERS ${CMAKE_SOURCE_DIR}/src/*.h ) +IF(LUA) + FILE(GLOB LUA_C_SOURCES + ${CMAKE_SOURCE_DIR}/src/lua/*.c + ) +ELSE(LUA) + SET(LUA_C_SOURCES "") +ENDIF(LUA) + # Get GIT version strings ADD_CUSTOM_TARGET( get_version @@ -37,6 +45,7 @@ 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) @@ -58,6 +67,12 @@ IF(TILES) ) ENDIF(WIN32) + 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(LUA) + ADD_DEPENDENCIES(cataclysm-tiles-common get_version) target_link_libraries(cataclysm-tiles cataclysm-tiles-common) @@ -121,13 +136,13 @@ IF(TILES) IF(BACKTRACE) target_link_libraries(cataclysm-tiles-common dbghelp.lib) - - IF(LIBBACKTRACE) - target_link_libraries(cataclysm-tiles-common backtrace) - ENDIF(LIBBACKTRACE) ENDIF(BACKTRACE) ENDIF(WIN32) + IF(LIBBACKTRACE) + target_link_libraries(cataclysm-tiles-common backtrace) + ENDIF(LIBBACKTRACE) + IF(RELEASE) install(TARGETS cataclysm-tiles DESTINATION ${BIN_PREFIX}) ENDIF(RELEASE) @@ -138,6 +153,7 @@ 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) @@ -158,6 +174,12 @@ IF(CURSES) ) ENDIF(WIN32) + 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(LUA) + ADD_DEPENDENCIES(cataclysm-common get_version) target_link_libraries(cataclysm cataclysm-common) @@ -183,13 +205,13 @@ IF(CURSES) IF(BACKTRACE) target_link_libraries(cataclysm-common dbghelp.lib) - - IF(LIBBACKTRACE) - target_link_libraries(cataclysm-common backtrace) - ENDIF(LIBBACKTRACE) ENDIF(BACKTRACE) ENDIF(WIN32) + IF(LIBBACKTRACE) + target_link_libraries(cataclysm-common backtrace) + ENDIF(LIBBACKTRACE) + IF(RELEASE) install(TARGETS cataclysm DESTINATION ${BIN_PREFIX}) ENDIF(RELEASE) diff --git a/src/action.cpp b/src/action.cpp index 228603bd4ec2..1ba8d3fb2311 100644 --- a/src/action.cpp +++ b/src/action.cpp @@ -267,6 +267,10 @@ std::string action_ident( action_id act ) return "help"; case ACTION_DEBUG: return "debug"; + case ACTION_LUA_CONSOLE: + return "lua_console"; + case ACTION_LUA_RELOAD: + return "lua_reload"; case ACTION_DISPLAY_SCENT: return "debug_scent"; case ACTION_DISPLAY_SCENT_TYPE: @@ -395,6 +399,8 @@ bool can_action_change_worldstate( const action_id act ) // Debug Functions case ACTION_TOGGLE_FULLSCREEN: case ACTION_DEBUG: + case ACTION_LUA_CONSOLE: + case ACTION_LUA_RELOAD: case ACTION_DISPLAY_SCENT: case ACTION_DISPLAY_SCENT_TYPE: case ACTION_DISPLAY_TEMPERATURE: @@ -919,7 +925,8 @@ action_id handle_main_menu() register_actions( { ACTION_HELP, ACTION_KEYBINDINGS, ACTION_OPTIONS, ACTION_AUTOPICKUP, ACTION_AUTONOTES, ACTION_SAFEMODE, ACTION_DISTRACTION_MANAGER, ACTION_COLOR, ACTION_WORLD_MODS, - ACTION_ACTIONMENU, ACTION_QUICKSAVE, ACTION_SAVE, ACTION_DEBUG + ACTION_ACTIONMENU, ACTION_QUICKSAVE, ACTION_SAVE, ACTION_DEBUG, ACTION_LUA_CONSOLE, + ACTION_LUA_RELOAD } ); uilist smenu; diff --git a/src/action.h b/src/action.h index ac92f63f545c..57d5744f0bee 100644 --- a/src/action.h +++ b/src/action.h @@ -275,6 +275,10 @@ enum action_id : int { ACTION_TOGGLE_FULLSCREEN, /** Open debug menu */ ACTION_DEBUG, + /** Open Lua console */ + ACTION_LUA_CONSOLE, + /** Hot-reload Lua code */ + ACTION_LUA_RELOAD, /** Toggle scent map */ ACTION_DISPLAY_SCENT, /** Toggle scent type map */ diff --git a/src/active_item_cache.cpp b/src/active_item_cache.cpp index aae8fe009494..dac406f1e365 100644 --- a/src/active_item_cache.cpp +++ b/src/active_item_cache.cpp @@ -46,12 +46,9 @@ void active_item_cache::add( item &it ) bool active_item_cache::empty() const { - for( std::pair>> active_queue : active_items ) { - if( !active_queue.second.empty() ) { - return false; - } - } - return true; + return std::all_of( active_items.begin(), active_items.end(), []( const auto & active_queue ) { + return active_queue.second.empty(); + } ); } std::vector active_item_cache::get() diff --git a/src/ballistics.cpp b/src/ballistics.cpp index 6dd88a17fe39..e3b7e7cb75d7 100644 --- a/src/ballistics.cpp +++ b/src/ballistics.cpp @@ -233,7 +233,8 @@ dealt_projectile_attack projectile_attack( const projectile &proj_arg, const tri proj.has_effect( ammo_effect_JET ); const char bullet = stream ? '#' : '*'; const bool no_item_damage = proj.has_effect( ammo_effect_NO_ITEM_DAMAGE ); - const bool do_draw_line = proj.has_effect( ammo_effect_DRAW_AS_LINE ); + const bool do_draw_line = proj.has_effect( ammo_effect_DRAW_AS_LINE ) || + get_option( "BULLETS_AS_LASERS" ); const bool null_source = proj.has_effect( ammo_effect_NULL_SOURCE ); // Determines whether it can penetrate obstacles const bool is_bullet = proj_arg.speed >= 200 && diff --git a/src/bodypart.h b/src/bodypart.h index 17d0d04e6a6e..508e623f8f69 100644 --- a/src/bodypart.h +++ b/src/bodypart.h @@ -9,6 +9,7 @@ #include #include "int_id.h" +#include "catalua_type_operators.h" #include "string_id.h" #include "translations.h" #include "location_ptr.h" @@ -136,6 +137,8 @@ struct body_part_type { int base_hp = 60; + LUA_TYPE_OPS( body_part_type, id ); + void load( const JsonObject &jo, const std::string &src ); void finalize(); void check() const; diff --git a/src/catalua.cpp b/src/catalua.cpp new file mode 100644 index 000000000000..82c8995fb082 --- /dev/null +++ b/src/catalua.cpp @@ -0,0 +1,431 @@ +#include "catalua.h" + +#include "debug.h" + +constexpr int LUA_API_VERSION = 1; + +#ifndef LUA + +#include "popup.h" + +namespace cata +{ + +// It's a dud +struct lua_state { + lua_state() = default; + ~lua_state() = default; +}; + +bool has_lua() +{ + return false; +} + +std::string get_lapi_version_string() +{ + return ""; +} + +void startup_lua_test() +{ + // Nothing to do here +} + +bool generate_lua_docs() +{ + // Nothing to do here + return false; +} + +void show_lua_console() +{ + query_popup() + .default_color( c_red ) + .allow_anykey( true ) + .message( "%s", "Can't open Lua console:\nthe game was compiled without Lua support." ) + .query(); +} + +void reload_lua_code() +{ + query_popup() + .default_color( c_red ) + .allow_anykey( true ) + .message( "%s", "Can't reload Lua code:\nthe game was compiled without Lua support." ) + .query(); +} + +void debug_write_lua_backtrace( std::ostream &/*out*/ ) +{ + // Nothing to do here +} + +bool save_world_lua_state( const std::string & ) +{ + return true; +} + +bool load_world_lua_state( const std::string & ) +{ + return true; +} + +std::unique_ptr make_wrapped_state() +{ + return std::unique_ptr( + new lua_state{}, lua_state_deleter{} + ); +} + +void init_global_state_tables( lua_state &, const std::vector & ) {} +void set_mod_being_loaded( lua_state &, const mod_id & ) {} +void clear_mod_being_loaded( lua_state & ) {} +void run_mod_preload_script( lua_state &, const mod_id & ) {} +void run_mod_finalize_script( lua_state &, const mod_id & ) {} +void run_mod_main_script( lua_state &, const mod_id & ) {} +void reg_lua_iuse_actors( lua_state &, Item_factory & ) {} + +template +void run_hooks( Args &&... ) {} + +void run_on_every_x_hooks( lua_state & ) {} + +} // namespace cata + +#else // LUA + +#include "catalua_sol.h" + +#include "avatar.h" +#include "catalua_console.h" +#include "catalua_impl.h" +#include "catalua_iuse_actor.h" +#include "catalua_readonly.h" +#include "catalua_serde.h" +#include "filesystem.h" +#include "fstream_utils.h" +#include "init.h" +#include "item_factory.h" +#include "map.h" +#include "mod_manager.h" +#include "path_info.h" +#include "point.h" +#include "worldfactory.h" + +namespace cata +{ + +bool has_lua() +{ + return true; +} + +std::string get_lapi_version_string() +{ + return string_format( "%d", get_lua_api_version() ); +} + +void startup_lua_test() +{ + sol::state lua = make_lua_state(); + std::string lua_startup_script = PATH_INFO::datadir() + "raw/on_game_start.lua"; + try { + run_lua_script( lua, lua_startup_script ); + } catch( std::runtime_error &e ) { + debugmsg( "%s", e.what() ); + } +} + +bool generate_lua_docs() +{ + sol::state lua = make_lua_state(); + lua.globals()["doc_gen_func"] = lua.create_table(); + std::string lua_doc_script = PATH_INFO::datadir() + "raw/generate_docs.lua"; + try { + run_lua_script( lua, lua_doc_script ); + sol::protected_function doc_gen_func = lua["doc_gen_func"]["impl"]; + sol::protected_function_result res = doc_gen_func(); + check_func_result( res ); + std::string ret = res; + write_to_file( PATH_INFO::lua_doc_output(), [&]( std::ostream & s ) { + s << ret; + } ); + } catch( std::runtime_error &e ) { + cata_printf( "%s\n", e.what() ); + return false; + } + return true; +} + +void show_lua_console() +{ + cata::show_lua_console_impl(); +} + +void reload_lua_code() +{ + cata::lua_state &state = *DynamicDataLoader::get_instance().lua; + const auto &packs = world_generator->active_world->active_mod_order; + try { + init::load_main_lua_scripts( state, packs ); + } catch( std::runtime_error &e ) { + debugmsg( "%s", e.what() ); + } + clear_mod_being_loaded( state ); +} + +void debug_write_lua_backtrace( std::ostream &out ) +{ + cata::lua_state &state = *DynamicDataLoader::get_instance().lua; + sol::state container; + + luaL_traceback( container.lua_state(), state.lua.lua_state(), "=== Lua backtrace report ===", 0 ); + + std::string data = sol::stack::pop( container ); + out << data << std::endl; +} + +static sol::table get_mod_storage_table( lua_state &state ) +{ + return state.lua.globals()["game"]["cata_internal"]["mod_storage"]; +} + +bool save_world_lua_state( const std::string &path ) +{ + lua_state &state = *DynamicDataLoader::get_instance().lua; + + const mod_management::t_mod_list &mods = world_generator->active_world->active_mod_order; + sol::table t = get_mod_storage_table( state ); + run_on_game_save_hooks( state ); + bool ret = write_to_file( path, [&]( std::ostream & stream ) { + JsonOut jsout( stream ); + jsout.start_object(); + for( const mod_id &mod : mods ) { + jsout.member( mod.str() ); + serialize_lua_table( t[mod.str()], jsout ); + } + jsout.end_object(); + }, "world_lua_state" ); + return ret; +} + +bool load_world_lua_state( const std::string &path ) +{ + lua_state &state = *DynamicDataLoader::get_instance().lua; + const mod_management::t_mod_list &mods = world_generator->active_world->active_mod_order; + sol::table t = get_mod_storage_table( state ); + + bool ret = read_from_file_optional( path, [&]( std::istream & stream ) { + JsonIn jsin( stream ); + JsonObject jsobj = jsin.get_object(); + + for( const mod_id &mod : mods ) { + if( !jsobj.has_object( mod.str() ) ) { + // Mod could have been added to existing save + continue; + } + JsonObject mod_obj = jsobj.get_object( mod.str() ); + deserialize_lua_table( t[mod.str()], mod_obj ); + } + } ); + + run_on_game_load_hooks( state ); + return ret; +} + +std::unique_ptr make_wrapped_state() +{ + std::unique_ptr ret( + new lua_state{ make_lua_state() }, + lua_state_deleter{} + ); + + sol::state &lua = ret->lua; + + sol::table game_table = lua.create_table(); + lua.globals()["game"] = game_table; + + return ret; +} + +void init_global_state_tables( lua_state &state, const std::vector &modlist ) +{ + sol::state &lua = state.lua; + + sol::table active_mods = lua.create_table(); + sol::table mod_runtime = lua.create_table(); + sol::table mod_storage = lua.create_table(); + sol::table hooks = lua.create_table(); + + for( size_t i = 0; i < modlist.size(); i++ ) { + active_mods[ i + 1 ] = modlist[i].str(); + mod_runtime[ modlist[i].str() ] = lua.create_table(); + mod_storage[ modlist[i].str() ] = lua.create_table(); + } + + // Main game data table + sol::table gt = lua.globals()["game"]; + + // Internal table that bypasses read-only facades + sol::table it = lua.create_table(); + gt["cata_internal"] = it; + it["active_mods"] = active_mods; + it["mod_runtime"] = mod_runtime; + it["mod_storage"] = mod_storage; + it["on_every_x_hooks"] = std::vector(); + gt["hooks"] = hooks; + + // Runtime infrastructure + gt["active_mods"] = make_readonly_table( lua, active_mods ); + gt["mod_runtime"] = make_readonly_table( lua, mod_runtime ); + gt["mod_storage"] = make_readonly_table( lua, mod_storage ); + gt["hooks"] = make_readonly_table( lua, hooks ); + + // iuse functions + gt["iuse_functions"] = lua.create_table(); + + // hooks + hooks["on_game_load"] = lua.create_table(); + hooks["on_game_save"] = lua.create_table(); + hooks["on_mapgen_postprocess"] = lua.create_table(); +} + +void set_mod_being_loaded( lua_state &state, const mod_id &mod ) +{ + sol::state &lua = state.lua; + lua.globals()["game"]["current_mod"] = mod.str(); +} + +void clear_mod_being_loaded( lua_state &state ) +{ + sol::state &lua = state.lua; + lua.globals()["game"]["current_mod"] = sol::nil; +} + +void run_mod_preload_script( lua_state &state, const mod_id &mod ) +{ + std::string script_path = mod->path + "/" + "preload.lua"; + + if( !file_exist( script_path ) ) { + return; + } + + run_lua_script( state.lua, script_path ); +} + +void run_mod_finalize_script( lua_state &state, const mod_id &mod ) +{ + std::string script_path = mod->path + "/" + "finalize.lua"; + + if( !file_exist( script_path ) ) { + return; + } + + run_lua_script( state.lua, script_path ); +} + +void run_mod_main_script( lua_state &state, const mod_id &mod ) +{ + std::string script_path = mod->path + "/" + "main.lua"; + + if( !file_exist( script_path ) ) { + return; + } + + run_lua_script( state.lua, script_path ); +} + +template +void run_hooks( lua_state &state, std::string_view hooks_table, Args &&...args ) +{ + sol::state &lua = state.lua; + sol::table hooks = lua.globals()["game"]["hooks"][hooks_table]; + for( auto &ref : hooks ) { + int idx = -1; + try { + idx = ref.first.as(); + sol::protected_function func = ref.second; + sol::protected_function_result res = func( std::forward( args )... ); + check_func_result( res ); + } catch( std::runtime_error &e ) { + debugmsg( "Failed to run hook %s[%d]: %s", hooks_table, idx, e.what() ); + break; + } + } +} + +void reg_lua_iuse_actors( lua_state &state, Item_factory &ifactory ) +{ + sol::state &lua = state.lua; + + sol::table funcs = lua.globals()["game"]["iuse_functions"]; + + for( auto &ref : funcs ) { + std::string key; + try { + key = ref.first.as(); + sol::protected_function func = ref.second; + ifactory.add_actor( std::make_unique( key, std::move( func ) ) ); + } catch( std::runtime_error &e ) { + debugmsg( "Failed to extract iuse_functions k='%s': %s", key, e.what() ); + break; + } + } +} + +void run_on_every_x_hooks( lua_state &state ) +{ + std::vector &master_table = + state.lua["game"]["cata_internal"]["on_every_x_hooks"]; + for( const auto &entry : master_table ) { + if( calendar::once_every( entry.interval ) ) { + for( auto &func : entry.functions ) { + try { + sol::protected_function_result res = func(); + check_func_result( res ); + } catch( std::runtime_error &e ) { + debugmsg( + "Failed to run hook on_every_x(interval = %s): %s", + to_string( entry.interval ), e.what() + ); + } + } + } + } +} + +} // namespace cata + +#endif // LUA + +namespace cata +{ + +int get_lua_api_version() +{ + return LUA_API_VERSION; +} + +void lua_state_deleter::operator()( lua_state *state ) const +{ + delete state; +} + +void run_on_game_save_hooks( lua_state &state ) +{ + run_hooks( state, "on_game_save" ); +} + +void run_on_game_load_hooks( lua_state &state ) +{ + run_hooks( state, "on_game_load" ); +} + +void run_on_mapgen_postprocess_hooks( lua_state &state, map &m, const tripoint &p, + const time_point &when ) +{ + run_hooks( state, "on_mapgen_postprocess", m, p, when ); +} + +} // namespace cata diff --git a/src/catalua.h b/src/catalua.h new file mode 100644 index 000000000000..1a7642a82ae4 --- /dev/null +++ b/src/catalua.h @@ -0,0 +1,50 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_H +#define CATA_SRC_CATALUA_H + +#include "type_id.h" + +#include + +class Item_factory; +class map; +class time_point; +struct tripoint; + +namespace cata +{ +struct lua_state; +struct lua_state_deleter { + void operator()( lua_state *state ) const; +}; + +bool has_lua(); +int get_lua_api_version(); +std::string get_lapi_version_string(); +void startup_lua_test(); +bool generate_lua_docs(); +void show_lua_console(); +void reload_lua_code(); +void debug_write_lua_backtrace( std::ostream &out ); + +bool save_world_lua_state( const std::string &path ); +bool load_world_lua_state( const std::string &path ); + +std::unique_ptr make_wrapped_state(); + +void init_global_state_tables( lua_state &state, const std::vector &modlist ); +void set_mod_being_loaded( lua_state &state, const mod_id &mod ); +void clear_mod_being_loaded( lua_state &state ); +void run_mod_preload_script( lua_state &state, const mod_id &mod ); +void run_mod_finalize_script( lua_state &state, const mod_id &mod ); +void run_mod_main_script( lua_state &state, const mod_id &mod ); +void run_on_game_load_hooks( lua_state &state ); +void run_on_game_save_hooks( lua_state &state ); +void run_on_every_x_hooks( lua_state &state ); +void run_on_mapgen_postprocess_hooks( lua_state &state, map &m, const tripoint &p, + const time_point &when ); +void reg_lua_iuse_actors( lua_state &state, Item_factory &ifactory ); + +} // namespace cata + +#endif // CATA_SRC_CATALUA_H diff --git a/src/catalua_bindings.cpp b/src/catalua_bindings.cpp new file mode 100644 index 000000000000..1e781439c66b --- /dev/null +++ b/src/catalua_bindings.cpp @@ -0,0 +1,818 @@ +#ifdef LUA +#include "catalua_bindings.h" + +#include "avatar.h" +#include "bodypart.h" +#include "calendar.h" +#include "catalua_bindings_utils.h" +#include "catalua_impl.h" +#include "catalua_log.h" +#include "catalua_luna_doc.h" +#include "catalua_luna.h" +#include "catalua.h" +#include "character.h" +#include "creature.h" +#include "distribution_grid.h" +#include "enum_conversions.h" +#include "field_type.h" +#include "field.h" +#include "game.h" +#include "itype.h" +#include "map.h" +#include "messages.h" +#include "monster.h" +#include "npc.h" +#include "player.h" +#include "popup.h" +#include "rng.h" +#include "translations.h" +#include "type_id.h" +#include "ui.h" + +std::string_view luna::detail::current_comment; + +std::string cata::detail::fmt_lua_va( sol::variadic_args va ) +{ + lua_State *L = va.lua_state(); + sol::state_view lua( L ); + + std::string msg; + for( auto it : va ) { + msg += lua["tostring"]( it ); + } + + return msg; +} + +namespace sol +{ +template <> +struct is_container : std::false_type {}; +template <> +struct is_container : std::false_type {}; +} // namespace sol + +struct item_stack_lua_it_state { + using it_t = item_stack::iterator; + it_t it; + it_t last; + + item_stack_lua_it_state( item_stack &stk ) + : it( stk.begin() ), last( stk.end() ) { + } +}; + +static std::tuple +item_stack_lua_next( + sol::user user_it_state, + sol::this_state l ) +{ + // this gets called + // to start the first iteration, and every + // iteration there after + + // the state you passed in item_stack_lua_pairs is argument 1 + // the key value is argument 2, but we do not + // care about the key value here + item_stack_lua_it_state &it_state = user_it_state; + auto &it = it_state.it; + if( it == it_state.last ) { + // return nil to signify that + // there's nothing more to work with. + return std::make_tuple( sol::object( sol::lua_nil ), + sol::object( sol::lua_nil ) ); + } + item *elem = &*it; + // 2 values are returned (pushed onto the stack): + // the key and the value + // the state is left alone + auto r = std::make_tuple( + sol::object( l, sol::in_place, it ), + sol::object( l, sol::in_place, elem ) ); + // the iterator must be moved forward one before we return + std::advance( it, 1 ); + return r; +} + +static auto item_stack_lua_pairs( item_stack &stk ) +{ + // pairs expects 3 returns: + // the "next" function on how to advance, + // the "table" itself or some state, + // and an initial key value (can be nil) + + // prepare our state + item_stack_lua_it_state it_state( stk ); + // sol::user is a space/time optimization over regular + // usertypes, it's incompatible with regular usertypes and + // stores the type T directly in lua without any pretty + // setup saves space allocation and a single dereference + return std::make_tuple( &item_stack_lua_next, + sol::user( std::move( it_state ) ), + sol::lua_nil ); +} + +void cata::detail::reg_creature_family( sol::state &lua ) +{ + { + // Specifying base classes here allows us to pass derived classes + // from Lua to C++ functions that expect base class. + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::no_constructor + ); + + // TODO: typesafe coords + DOC( "Position within map" ); + luna::set_fx( ut, "get_pos_ms", &Creature::pos ); + + luna::set_fx( ut, "is_monster", &Creature::is_monster ); + luna::set_fx( ut, "as_monster", sol::resolve( &Creature::as_monster ) ); + luna::set_fx( ut, "is_npc", &Creature::is_npc ); + luna::set_fx( ut, "as_npc", sol::resolve( &Creature::as_npc ) ); + luna::set_fx( ut, "is_avatar", &Creature::is_avatar ); + luna::set_fx( ut, "as_avatar", sol::resolve( &Creature::as_avatar ) ); + + luna::set_fx( ut, "has_effect", []( const Creature & cr, const efftype_id & eff, + sol::optional bpid ) -> bool { + if( bpid.has_value() ) + { + return cr.has_effect( eff, *bpid ); + } else + { + return cr.has_effect( eff ); + } + } ); + + luna::set_fx( ut, "get_effect_dur", []( const Creature & cr, const efftype_id & eff, + sol::optional bpid ) -> time_duration { + body_part bp = bpid ? ( *bpid ) -> token : num_bp; + return cr.get_effect_dur( eff, bp ); + } ); + + luna::set_fx( ut, "get_effect_int", []( const Creature & cr, const efftype_id & eff, + sol::optional bpid ) -> int { + body_part bp = bpid ? ( *bpid ) -> token : num_bp; + return cr.get_effect_int( eff, bp ); + } ); + + DOC( "Effect type, duration, bodypart and intensity" ); + luna::set_fx( ut, "add_effect", []( Creature & cr, const efftype_id & eff, + const time_duration & dur, + sol::optional bpid, + sol::optional intensity + ) { + int eint = intensity ? *intensity : 0; + body_part bp = bpid ? ( *bpid ) -> token : num_bp; + cr.add_effect( eff, dur, bp, eint ); + } ); + + luna::set_fx( ut, "remove_effect", []( Creature & cr, const efftype_id & eff, + sol::optional bpid ) -> bool { + body_part bp = bpid ? ( *bpid ) -> token : num_bp; + return cr.remove_effect( eff, bp ); + } ); + } + + { + luna::new_usertype( + lua, + luna::bases(), + luna::no_constructor + ); + luna::new_usertype( + lua, + luna::bases(), + luna::no_constructor + ); + luna::new_usertype( + lua, + luna::bases(), + luna::no_constructor + ); + luna::new_usertype( + lua, + luna::bases(), + luna::no_constructor + ); + luna::new_usertype( + lua, + luna::bases(), + luna::no_constructor + ); + } +} + +void cata::detail::reg_item( sol::state &lua ) +{ + { + sol::usertype ut = luna::new_usertype( lua, luna::no_bases, luna::no_constructor ); + + luna::set_fx( ut, "get_type", &item::typeId ); + + DOC( "Check for variable of any type" ); + luna::set_fx( ut, "has_var", &item::has_var ); + DOC( "Erase variable" ); + luna::set_fx( ut, "erase_var", &item::erase_var ); + DOC( "Erase all variables" ); + luna::set_fx( ut, "clear_vars", &item::clear_vars ); + + DOC( "Get variable as string" ); + luna::set_fx( ut, "get_var_str", + sol::resolve + ( &item::get_var ) ); + DOC( "Get variable as float number" ); + luna::set_fx( ut, "get_var_num", + sol::resolve( &item::get_var ) ); + DOC( "Get variable as tripoint" ); + luna::set_fx( ut, "get_var_tri", + sol::resolve + ( &item::get_var ) ); + + luna::set_fx( ut, "set_var_str", sol::resolve + ( &item::set_var ) ); + luna::set_fx( ut, "set_var_num", + sol::resolve( &item::set_var ) ); + luna::set_fx( ut, "set_var_tri", + sol::resolve( &item::set_var ) ); + } +} + +void cata::detail::reg_map( sol::state &lua ) +{ + // Register 'map' class to be used in Lua + { + sol::usertype ut = luna::new_usertype( lua, luna::no_bases, luna::no_constructor ); + + DOC( "Convert local ms -> absolute ms" ); + luna::set_fx( ut, "get_abs_ms", sol::resolve( &map::getabs ) ); + DOC( "Convert absolute ms -> local ms" ); + luna::set_fx( ut, "get_local_ms", + sol::resolve( &map::getlocal ) ); + + luna::set_fx( ut, "get_map_size_in_submaps", &map::getmapsize ); + DOC( "In map squares" ); + luna::set_fx( ut, "get_map_size", []( const map & m ) -> int { + return m.getmapsize() * SEEX; + } ); + + luna::set_fx( ut, "has_items_at", &map::has_items ); + luna::set_fx( ut, "get_items_at", []( map & m, const tripoint & p ) -> std::unique_ptr { + return std::make_unique( m.i_at( p ) ); + } ); + + + luna::set_fx( ut, "get_ter_at", sol::resolve( &map::ter ) ); + luna::set_fx( ut, "set_ter_at", + sol::resolve( &map::ter_set ) ); + + luna::set_fx( ut, "get_furn_at", sol::resolve( &map::furn ) ); + luna::set_fx( ut, "set_furn_at", []( map & m, const tripoint & p, const furn_id & id ) { + m.furn_set( p, id ); + } ); + + luna::set_fx( ut, "has_field_at", []( const map & m, const tripoint & p, + const field_type_id & fid ) -> bool { + return !!m.field_at( p ).find_field( fid ); + } ); + luna::set_fx( ut, "get_field_int_at", &map::get_field_intensity ); + luna::set_fx( ut, "get_field_age_at", &map::get_field_age ); + luna::set_fx( ut, "mod_field_int_at", &map::mod_field_intensity ); + luna::set_fx( ut, "mod_field_age_at", &map::mod_field_age ); + luna::set_fx( ut, "set_field_int_at", &map::set_field_intensity ); + luna::set_fx( ut, "set_field_age_at", &map::set_field_age ); + luna::set_fx( ut, "add_field_at", []( map & m, const tripoint & p, const field_type_id & fid, + int intensity, const time_duration & age ) -> bool { + return m.add_field( p, fid, intensity, age ); + } ); + luna::set_fx( ut, "remove_field_at", &map::remove_field ); + } + + // Register 'tinymap' class to be used in Lua + { + luna::new_usertype( lua, luna::bases(), luna::no_constructor ); + } + + // Register 'item_stack' class to be used in Lua + { + DOC( "Iterate over this using pairs()" ); + sol::usertype ut = luna::new_usertype( lua, luna::no_bases, + luna::no_constructor ); + + luna::set_fx( ut, sol::meta_function::pairs, item_stack_lua_pairs ); + } + + // Register 'map_stack' class to be used in Lua + { + sol::usertype ut = luna::new_usertype( lua, luna::bases(), + luna::no_constructor ); + + luna::set_fx( ut, "as_item_stack", []( map_stack & ref ) -> item_stack& { + return ref; + } ); + } +} + +void cata::detail::reg_distribution_grid( sol::state &lua ) +{ + { + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::no_constructor + ); + + DOC( "Boolean argument controls recursive behavior" ); + luna::set_fx( ut, "get_resource", &distribution_grid::get_resource ); + DOC( "Boolean argument controls recursive behavior" ); + luna::set_fx( ut, "mod_resource", &distribution_grid::mod_resource ); + } + + { + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::no_constructor + ); + + luna::set_fx( ut, "get_grid_at_abs_ms", []( distribution_grid_tracker & tr, const tripoint & p ) + -> distribution_grid& { + return tr.grid_at( tripoint_abs_ms( p ) ); + } ); + } + +} + +void cata::detail::reg_ui_elements( sol::state &lua ) +{ + { + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::constructors < + uilist() + > () + ); + luna::set_fx( ut, "title", []( uilist & ui, const std::string & text ) { + ui.title = text; + } ); + DOC( "Return value, text" ); + luna::set_fx( ut, "add", []( uilist & ui, int retval, const std::string & text ) { + ui.addentry( retval, true, MENU_AUTOASSIGN, text ); + } ); + DOC( "Returns retval for selected entry, or a negative number on fail/cancel" ); + luna::set_fx( ut, "query", []( uilist & ui ) { + ui.query(); + return ui.ret; + } ); + } + + { + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::constructors < + query_popup() + > () + ); + luna::set_fx( ut, "message", []( query_popup & popup, sol::variadic_args va ) { + popup.message( "%s", cata::detail::fmt_lua_va( va ) ); + } ); + luna::set_fx( ut, "message_color", []( query_popup & popup, color_id col ) { + popup.default_color( get_all_colors().get( col ) ); + } ); + DOC( "Set whether to allow any key" ); + luna::set_fx( ut, "allow_any_key", []( query_popup & popup, bool val ) { + popup.allow_anykey( val ); + } ); + DOC( "Returns selected action" ); + luna::set_fx( ut, "query", []( query_popup & popup ) { + return popup.query().action; + } ); + } +} + +void cata::detail::reg_constants( sol::state &lua ) +{ + DOC( "Various game constants" ); + luna::userlib lib = luna::begin_lib( lua, "const" ); + + luna::set( lib, "OM_OMT_SIZE", OMAPX ); + luna::set( lib, "OM_SM_SIZE", OMAPX * 2 ); + luna::set( lib, "OM_MS_SIZE", OMAPX * 2 * SEEX ); + luna::set( lib, "OMT_SM_SIZE", 2 ); + luna::set( lib, "OMT_MS_SIZE", SEEX * 2 ); + luna::set( lib, "SM_MS_SIZE", SEEX ); + + luna::finalize_lib( lib ); +} + +static void lua_log_info_impl( sol::variadic_args va ) +{ + std::string msg = cata::detail::fmt_lua_va( va ); + + DebugLog( DL::Info, DC::Lua ) << msg; + cata::get_lua_log_instance().add( cata::LuaLogLevel::Info, std::move( msg ) ); +} + +static void lua_log_warn_impl( sol::variadic_args va ) +{ + std::string msg = cata::detail::fmt_lua_va( va ); + + DebugLog( DL::Warn, DC::Lua ) << msg; + cata::get_lua_log_instance().add( cata::LuaLogLevel::Warn, std::move( msg ) ); +} + +static void lua_log_error_impl( sol::variadic_args va ) +{ + std::string msg = cata::detail::fmt_lua_va( va ); + + DebugLog( DL::Error, DC::Lua ) << msg; + cata::get_lua_log_instance().add( cata::LuaLogLevel::Error, std::move( msg ) ); +} + +static void lua_debugmsg_impl( sol::variadic_args va ) +{ + std::string msg = cata::detail::fmt_lua_va( va ); + + debugmsg( "%s", msg ); + cata::get_lua_log_instance().add( cata::LuaLogLevel::DebugMsg, std::move( msg ) ); +} + +void cata::detail::reg_debug_api( sol::state &lua ) +{ + DOC( "Debugging and logging API." ); + luna::userlib lib = luna::begin_lib( lua, "gdebug" ); + + luna::set_fx( lib, "log_info", &lua_log_info_impl ); + luna::set_fx( lib, "log_warn", &lua_log_warn_impl ); + luna::set_fx( lib, "log_error", &lua_log_error_impl ); + luna::set_fx( lib, "debugmsg", &lua_debugmsg_impl ); + luna::set_fx( lib, "clear_lua_log", []() { + cata::get_lua_log_instance().clear(); + } ); + luna::set_fx( lib, "set_log_capacity", []( int v ) { + cata::get_lua_log_instance().set_log_capacity( v ); + } ); + luna::set_fx( lib, "reload_lua_code", &cata::reload_lua_code ); + luna::set_fx( lib, "save_game", []() -> bool { + return g->save(); + } ); + + luna::finalize_lib( lib ); +} + +void cata::detail::override_default_print( sol::state &lua ) +{ + lua.globals()["print"] = &lua_log_info_impl; +} + +void cata::detail::forbid_unsafe_functions( sol::state &lua ) +{ + auto g = lua.globals(); + g["dofile"] = sol::nil; + g["loadfile"] = sol::nil; + g["load"] = sol::nil; + g["loadstring"] = sol::nil; +} + +static void add_msg_lua( game_message_type t, sol::variadic_args va ) +{ + if( va.size() == 0 ) { + // Nothing to print + return; + } + + std::string msg = cata::detail::fmt_lua_va( va ); + add_msg( t, msg ); +} + +void cata::detail::reg_game_api( sol::state &lua ) +{ + DOC( "Global game methods" ); + luna::userlib lib = luna::begin_lib( lua, "gapi" ); + + luna::set_fx( lib, "get_avatar", &get_avatar ); + luna::set_fx( lib, "get_map", &get_map ); + luna::set_fx( lib, "get_distribution_grid_tracker", &get_distribution_grid_tracker ); + luna::set_fx( lib, "get_character_name", []( const Character & you ) -> std::string { + return you.name; + } ); + luna::set_fx( lib, "add_msg", sol::overload( + add_msg_lua, + []( sol::variadic_args va ) { + add_msg_lua( game_message_type::m_neutral, va ); + } + ) ); + + luna::set_fx( lib, "current_turn", []() -> time_point { return calendar::turn; } ); + luna::set_fx( lib, "turn_zero", []() -> time_point { return calendar::turn_zero; } ); + luna::set_fx( lib, "before_time_starts", []() -> time_point { return calendar::before_time_starts; } ); + luna::set_fx( lib, "rng", sol::resolve( &rng ) ); + luna::set_fx( lib, "add_on_every_x_hook", []( sol::this_state lua_this, time_duration interval, + sol::protected_function f ) { + sol::state_view lua( lua_this ); + std::vector &hooks = lua["game"]["cata_internal"]["on_every_x_hooks"]; + for( auto &entry : hooks ) { + if( entry.interval == interval ) { + entry.functions.push_back( f ); + return; + } + } + std::vector vec; + vec.push_back( f ); + hooks.push_back( on_every_x_hooks{ interval, vec } ); + } ); + + luna::finalize_lib( lib ); +} + +// We have to alias the function here because VS compiler +// confuses namespaces 'detail' and 'cata::detail' +const auto &gettext_raw = sol::resolve + ( &detail::_translate_internal ); + +void cata::detail::reg_locale_api( sol::state &lua ) +{ + DOC( "Localization API." ); + luna::userlib lib = luna::begin_lib( lua, "locale" ); + + DOC( "Expects english source string, returns translated string." ); + luna::set_fx( lib, "gettext", gettext_raw ); + DOC( "First is english singular string, second is english plural string. Number is amount to translate for." ); + luna::set_fx( lib, "vgettext", &vgettext ); + DOC( "First is context string. Second is english source string." ); + luna::set_fx( lib, "pgettext", &pgettext ); + DOC( "First is context string. Second is english singular string. third is english plural. Number is amount to translate for." ); + luna::set_fx( lib, "vpgettext", &vpgettext ); + + luna::finalize_lib( lib ); +} + +template +void reg_enum( sol::state &lua ) +{ + // Sol2 has new_enum(...) function, but it needs to know all value-string + // pairs at compile time, so we can't use it with io::enum_to_string. + // + // As such, hack it by creating read-only table. + + luna::userenum et = luna::begin_enum( lua ); + + using Int = std::underlying_type_t; + constexpr Int max = static_cast( enum_traits::last ); + + for( Int i = 0; i < max; ++i ) { + E e = static_cast( i ); + std::string key = io::enum_to_string( e ); + luna::add_val( et, key, e ); + } + + luna::finalize_enum( et ); +} + +void cata::detail::reg_colors( sol::state &lua ) +{ + // Colors are not enums, we have to do them manually + luna::userenum et = luna::begin_enum( lua ); + + using Int = std::underlying_type_t; + constexpr Int max = static_cast( color_id::num_colors ); + + for( Int i = 0; i < max; ++i ) { + color_id e = static_cast( i ); + std::string key = get_all_colors().id_to_name( e ); + luna::add_val( et, key, e ); + } + + luna::finalize_enum( et ); +} + +void cata::detail::reg_enums( sol::state &lua ) +{ + reg_enum( lua ); +} + +void cata::detail::reg_hooks_examples( sol::state &lua ) +{ + DOC( "Documentation for hooks" ); + luna::userlib lib = luna::begin_lib( lua, "hooks_doc" ); + + DOC( "Called when game is about to save" ); + luna::set_fx( lib, "on_game_save", []() {} ); + DOC( "Called right after game has loaded" ); + luna::set_fx( lib, "on_game_load", []() {} ); + DOC( "Called every in-game period" ); + luna::set_fx( lib, "on_every_x", []() {} ); + DOC( "Called right after mapgen has completed. " + "Map argument is the tinymap that represents 24x24 area (2x2 submaps, or 1x1 omt), " + "tripoint is the absolute omt pos, and time_point is the current time (for time-based effects)." + ); + luna::set_fx( lib, "on_mapgen_postprocess", []( map &, const tripoint &, const time_point & ) {} ); + + luna::finalize_lib( lib ); +} + +void cata::detail::reg_time_types( sol::state &lua ) +{ + DOC( "Library for dealing with time primitives." ); + + { + DOC( "Represent fixed point in time" ); + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::constructors < time_point() > () + ); + + // Constructor method + luna::set_fx( ut, "from_turn", &time_point::from_turn ); + + // Methods + luna::set_fx( ut, "to_turn", []( const time_point & tp ) -> int { + return to_turn( tp ); + } ); + + luna::set_fx( ut, "is_night", &is_night ); + luna::set_fx( ut, "is_day", &is_day ); + luna::set_fx( ut, "is_dusk", &is_dusk ); + luna::set_fx( ut, "is_dawn", &is_dawn ); + + luna::set_fx( ut, "second_of_minute", []( const time_point & tp ) -> int { + return to_turn( tp ) % 60; + } ); + luna::set_fx( ut, "minute_of_hour", []( const time_point & tp ) -> int { + return minute_of_hour( tp ); + } ); + luna::set_fx( ut, "hour_of_day", []( const time_point & tp ) -> int { + return hour_of_day( tp ); + } ); + + // (De-)Serialization + reg_serde_functions( ut ); + + luna::set_fx( ut, "to_string_time_of_day", &to_string_time_of_day ); + + // To string + // We're using Lua meta function here to make it work seamlessly with native Lua tostring() + luna::set_fx( ut, sol::meta_function::to_string, + sol::resolve( to_string ) ); + + // Equality operator + // It's defined as inline friend function inside point class, we can't access it and so have to improvise + luna::set_fx( ut, sol::meta_function::equal_to, []( const time_point & a, const time_point & b ) { + return a == b; + } ); + + // Less-then operator + // Same deal as with equality operator + luna::set_fx( ut, sol::meta_function::less_than, []( const time_point & a, const time_point & b ) { + return a < b; + } ); + + // Arithmetic operators + luna::set_fx( ut, sol::meta_function::addition, + []( const time_point & a, const time_duration & b ) -> time_point { + return a + b; + } + ); + luna::set_fx( ut, sol::meta_function::subtraction, + sol::overload( + []( const time_point & a, const time_point & b ) -> time_duration { + return a - b; + }, + []( const time_point & a, const time_duration & b ) -> time_point { + return a - b; + } + ) ); + } + { + DOC( "Represent duration between 2 fixed points in time" ); + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::constructors < time_duration() > () + ); + + // Constructor methods + luna::set_fx( ut, "from_turns", []( int t ) { + return time_duration::from_turns( t ); + } ); + luna::set_fx( ut, "from_seconds", []( int t ) { + return time_duration::from_seconds( t ); + } ); + luna::set_fx( ut, "from_minutes", []( int t ) { + return time_duration::from_minutes( t ); + } ); + luna::set_fx( ut, "from_hours", []( int t ) { + return time_duration::from_hours( t ); + } ); + luna::set_fx( ut, "from_days", []( int t ) { + return time_duration::from_days( t ); + } ); + luna::set_fx( ut, "from_weeks", []( int t ) { + return time_duration::from_weeks( t ); + } ); + + luna::set_fx( ut, "make_random", []( const time_duration & lo, const time_duration & hi ) { + return rng( lo, hi ); + } ); + + luna::set_fx( ut, "to_turns", []( const time_duration & t ) -> int { + return to_turns( t ); + } ); + luna::set_fx( ut, "to_seconds", []( const time_duration & t ) -> int { + return to_seconds( t ); + } ); + luna::set_fx( ut, "to_minutes", []( const time_duration & t ) -> int { + return to_minutes( t ); + } ); + luna::set_fx( ut, "to_hours", []( const time_duration & t ) -> int { + return to_hours( t ); + } ); + luna::set_fx( ut, "to_days", []( const time_duration & t ) -> int { + return to_days( t ); + } ); + luna::set_fx( ut, "to_weeks", []( const time_duration & t ) -> int { + return to_weeks( t ); + } ); + + // (De-)Serialization + reg_serde_functions( ut ); + + // To string + // We're using Lua meta function here to make it work seamlessly with native Lua tostring() + luna::set_fx( ut, sol::meta_function::to_string, + sol::resolve( to_string ) ); + + luna::set_fx( ut, sol::meta_function::addition, []( const time_duration & a, + const time_duration & b ) { + return a + b; + } ); + luna::set_fx( ut, sol::meta_function::subtraction, []( const time_duration & a, + const time_duration & b ) { + return a - b; + } ); + luna::set_fx( ut, sol::meta_function::multiplication, []( const time_duration & a, int b ) { + return a * b; + } ); + luna::set_fx( ut, sol::meta_function::division, []( const time_duration & a, int b ) { + return a / b; + } ); + luna::set_fx( ut, sol::meta_function::unary_minus, []( const time_duration & a ) { + return -a; + } ); + } +} + +void cata::detail::reg_testing_library( sol::state &lua ) +{ + DOC( "Library for testing purposes" ); + luna::userlib lib = luna::begin_lib( lua, "tests_lib" ); + + // Regression test for https://github.com/ThePhD/sol2/issues/1444 + luna::set_fx( lib, "my_awesome_lambda_1", []() -> int { + return 1; + } ); + luna::set_fx( lib, "my_awesome_lambda_2", []() -> int { + return 2; + } ); + + luna::finalize_lib( lib ); +} + +void cata::reg_all_bindings( sol::state &lua ) +{ + using namespace detail; + + override_default_print( lua ); + forbid_unsafe_functions( lua ); + reg_debug_api( lua ); + reg_game_api( lua ); + reg_locale_api( lua ); + reg_creature_family( lua ); + reg_point_tripoint( lua ); + reg_item( lua ); + reg_map( lua ); + reg_distribution_grid( lua ); + reg_ui_elements( lua ); + reg_colors( lua ); + reg_enums( lua ); + reg_game_ids( lua ); + reg_coords_library( lua ); + reg_constants( lua ); + reg_hooks_examples( lua ); + reg_types( lua ); + reg_time_types( lua ); + reg_testing_library( lua ); +} + +#endif diff --git a/src/catalua_bindings.h b/src/catalua_bindings.h new file mode 100644 index 000000000000..1ae582075ca4 --- /dev/null +++ b/src/catalua_bindings.h @@ -0,0 +1,42 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_BINDINGS_H +#define CATA_SRC_CATALUA_BINDINGS_H + +#include "catalua_sol_fwd.h" + +#include + +namespace cata +{ +namespace detail +{ +std::string fmt_lua_va( sol::variadic_args va ); +void override_default_print( sol::state &lua ); +void forbid_unsafe_functions( sol::state &lua ); + +void reg_colors( sol::state &lua ); +void reg_constants( sol::state &lua ); +void reg_coords_library( sol::state &lua ); +void reg_creature_family( sol::state &lua ); +void reg_debug_api( sol::state &lua ); +void reg_distribution_grid( sol::state &lua ); +void reg_enums( sol::state &lua ); +void reg_game_api( sol::state &lua ); +void reg_locale_api( sol::state &lua ); +void reg_hooks_examples( sol::state &lua ); +void reg_item( sol::state &lua ); +void reg_map( sol::state &lua ); +void reg_point_tripoint( sol::state &lua ); +void reg_testing_library( sol::state &lua ); +void reg_time_types( sol::state &lua ); +void reg_game_ids( sol::state &lua ); +void reg_types( sol::state &lua ); +void reg_ui_elements( sol::state &lua ); + +} // namespace detail + +void reg_all_bindings( sol::state &lua ); + +} // namespace cata + +#endif // CATA_SRC_CATALUA_BINDINGS_H diff --git a/src/catalua_bindings_coords.cpp b/src/catalua_bindings_coords.cpp new file mode 100644 index 000000000000..90441a27d4c9 --- /dev/null +++ b/src/catalua_bindings_coords.cpp @@ -0,0 +1,209 @@ +#ifdef LUA +#include "catalua_bindings.h" + +#include "catalua_bindings_utils.h" +#include "catalua_luna_doc.h" +#include "catalua_luna.h" +#include "coordinates.h" +#include "json.h" +#include "line.h" +#include "point.h" + +void cata::detail::reg_point_tripoint( sol::state &lua ) +{ + // Register 'point' class to be used in Lua + { + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::constructors < + point(), + point( const point & ), + point( int, int ) + > () + ); + + // Members + luna::set( ut, "x", &point::x ); + luna::set( ut, "y", &point::y ); + + // Methods + luna::set_fx( ut, "abs", &point::abs ); + luna::set_fx( ut, "rotate", &point::rotate ); + + // (De-)Serialization + reg_serde_functions( ut ); + + // To string + // We're using Lua meta function here to make it work seamlessly with native Lua tostring() + luna::set_fx( ut, sol::meta_function::to_string, &point::to_string ); + + // Equality operator + // It's defined as inline friend function inside point class, we can't access it and so have to improvise + luna::set_fx( ut, sol::meta_function::equal_to, []( const point & a, const point & b ) { + return a == b; + } ); + + // Less-then operator + // Same deal as with equality operator + luna::set_fx( ut, sol::meta_function::less_than, []( const point & a, const point & b ) { + return a < b; + } ); + + // Arithmetic operators + // point + point + luna::set_fx( ut, sol::meta_function::addition, &point::operator+ ); + // point - point + // sol::resolve here makes it possible to specify which overload to use + luna::set_fx( ut, sol::meta_function::subtraction, sol::resolve< point( point ) const > + ( &point::operator- ) ); + // point * int + luna::set_fx( ut, sol::meta_function::multiplication, &point::operator* ); + // point / float + luna::set_fx( ut, sol::meta_function::division, &point::operator/ ); + // point / int + luna::set_fx( ut, sol::meta_function::floor_division, &point::operator/ ); + // -point + // sol::resolve here makes it possible to specify which overload to use + luna::set_fx( ut, sol::meta_function::unary_minus, + sol::resolve< point() const >( &point::operator- ) ); + } + + // Register 'tripoint' class to be used in Lua + { + sol::usertype ut = + luna::new_usertype( + lua, + luna::no_bases, + luna::constructors < + tripoint(), + tripoint( const point &, int ), + tripoint( const tripoint & ), + tripoint( int, int, int ) + > () + ); + + // Members + luna::set( ut, "x", &tripoint::x ); + luna::set( ut, "y", &tripoint::y ); + luna::set( ut, "z", &tripoint::z ); + + // Methods + luna::set_fx( ut, "abs", &tripoint::abs ); + luna::set_fx( ut, "xy", &tripoint::xy ); + luna::set_fx( ut, "rotate_2d", &tripoint::rotate_2d ); + + // (De-)Serialization + reg_serde_functions( ut ); + + // To string + // We're using Lua meta function here to make it work seamlessly with native Lua tostring() + luna::set_fx( ut, sol::meta_function::to_string, &tripoint::to_string ); + + // Equality operator + // It's defined as inline friend function inside point class, we can't access it and so have to improvise + luna::set_fx( ut, sol::meta_function::equal_to, []( const tripoint & a, const tripoint & b ) { + return a == b; + } ); + + // Less-then operator + // Same deal as with equality operator + luna::set_fx( ut, sol::meta_function::less_than, []( const tripoint & a, const tripoint & b ) { + return a < b; + } ); + + // Arithmetic operators + // tripoint + tripoint (overload 1) + // tripoint + point (overload 2) + luna::set_fx( ut, sol::meta_function::addition, sol::overload( + sol::resolve< tripoint( const tripoint & ) const > ( &tripoint::operator+ ), + sol::resolve< tripoint( point ) const > ( &tripoint::operator+ ) + ) ); + // tripoint - tripoint (overload 1) + // tripoint - point (overload 2) + luna::set_fx( ut, sol::meta_function::subtraction, sol::overload( + sol::resolve< tripoint( const tripoint & ) const > ( &tripoint::operator- ), + sol::resolve< tripoint( point ) const > ( &tripoint::operator- ) + ) ); + // tripoint * int + luna::set_fx( ut, sol::meta_function::multiplication, &tripoint::operator* ); + // tripoint / float + luna::set_fx( ut, sol::meta_function::division, &tripoint::operator/ ); + // tripoint / int + luna::set_fx( ut, sol::meta_function::floor_division, &tripoint::operator/ ); + // -tripoint + // sol::resolve here makes it possible to specify which overload to use + luna::set_fx( ut, sol::meta_function::unary_minus, + sol::resolve< tripoint() const >( &tripoint::operator- ) ); + } +} + +void cata::detail::reg_coords_library( sol::state &lua ) +{ + DOC( "Methods for manipulating coord systems and calculating distance" ); + luna::userlib lib = luna::begin_lib( lua, "coords" ); + + luna::set_fx( lib, "ms_to_sm", []( const tripoint & raw ) -> std::tuple { + tripoint_rel_ms fine( raw ); + tripoint_rel_sm rough; + point_sm_ms remain; + std::tie( rough, remain ) = coords::project_remain( fine ); + return std::make_pair( rough.raw(), remain.raw() ); + } ); + luna::set_fx( lib, "ms_to_omt", []( const tripoint & raw ) -> std::tuple { + tripoint_rel_ms fine( raw ); + tripoint_rel_omt rough; + point_omt_ms remain; + std::tie( rough, remain ) = coords::project_remain( fine ); + return std::make_pair( rough.raw(), remain.raw() ); + } ); + luna::set_fx( lib, "ms_to_om", []( const tripoint & raw ) -> std::tuple { + tripoint_rel_ms fine( raw ); + point_rel_om rough; + coords::coord_point remain; + std::tie( rough, remain ) = coords::project_remain( fine ); + return std::make_pair( rough.raw(), remain.raw() ); + } ); + + luna::set_fx( lib, "sm_to_ms", []( const tripoint & raw_rough, + sol::optional raw_remain ) -> tripoint { + tripoint_rel_sm rough( raw_rough ); + point_sm_ms remain( raw_remain ? *raw_remain : point_zero ); + tripoint_rel_ms fine = coords::project_combine( rough, remain ); + return fine.raw(); + } ); + luna::set_fx( lib, "omt_to_ms", []( const tripoint & raw_rough, + sol::optional raw_remain ) -> tripoint { + tripoint_rel_omt rough( raw_rough ); + point_omt_ms remain( raw_remain ? *raw_remain : point_zero ); + tripoint_rel_ms fine = coords::project_combine( rough, remain ); + return fine.raw(); + } ); + luna::set_fx( lib, "om_to_ms", []( const point & raw_rough, + sol::optional raw_remain ) -> tripoint { + point_rel_om rough( raw_rough ); + coords::coord_point remain( + raw_remain ? *raw_remain : tripoint_zero + ); + tripoint_rel_ms fine = coords::project_combine( rough, remain ); + return fine.raw(); + } ); + + luna::set_fx( lib, "rl_dist", sol::overload( + sol::resolve( rl_dist ), + sol::resolve( rl_dist ) + ) ); + luna::set_fx( lib, "trig_dist", sol::overload( + sol::resolve( trig_dist ), + sol::resolve( trig_dist ) + ) ); + luna::set_fx( lib, "square_dist", sol::overload( + sol::resolve( square_dist ), + sol::resolve( square_dist ) + ) ); + + luna::finalize_lib( lib ); +} + +#endif diff --git a/src/catalua_bindings_ids.cpp b/src/catalua_bindings_ids.cpp new file mode 100644 index 000000000000..058615b2978b --- /dev/null +++ b/src/catalua_bindings_ids.cpp @@ -0,0 +1,153 @@ +#ifdef LUA +#include "catalua_bindings.h" + +#include "bodypart.h" +#include "catalua_luna_doc.h" +#include "catalua_luna.h" +#include "effect.h" +#include "faction.h" +#include "field_type.h" +#include "itype.h" +#include "json.h" +#include "mapdata.h" +#include "type_id.h" + + +template +void reg_id( sol::state &lua ) +{ + using SID = string_id; + using IID = int_id; + { + // Register string_id class under given name + sol::usertype ut; + if constexpr( do_int_id ) { + ut = luna::new_usertype( lua, luna::no_bases, luna::constructors < + SID(), + SID( const SID & ), + SID( const IID & ), + SID( std::string ) + > () + ); + } else { + ut = luna::new_usertype( lua, luna::no_bases, luna::constructors < + SID(), + SID( const SID & ), + SID( std::string ) + > () + ); + } + + luna::set_fx( ut, "obj", []( const SID & sid ) -> const T* { + return &sid.obj(); + } ); + if constexpr( do_int_id ) { + luna::set_fx( ut, "int_id", &SID::id ); + luna::set_fx( ut, "implements_int_id", []() { + return true; + } ); + } else { + luna::set_fx( ut, "implements_int_id", []() { + return false; + } ); + } + luna::set_fx( ut, "is_null", &SID::is_null ); + luna::set_fx( ut, "is_valid", &SID::is_valid ); + luna::set_fx( ut, "str", &SID::c_str ); + luna::set_fx( ut, "NULL_ID", &SID::NULL_ID ); + luna::set_fx( ut, sol::meta_function::to_string, []( const SID & id ) -> std::string { + return string_format( "%s[%s]", luna::detail::luna_traits::name, id.c_str() ); + } ); + + // (De-)Serialization + luna::set_fx( ut, "serialize", []( const SID & ut, JsonOut & jsout ) { + jsout.write( ut.str() ); + } ); + luna::set_fx( ut, "deserialize", []( SID & ut, JsonIn & jsin ) { + ut = SID( jsin.get_string() ); + } ); + } + if constexpr( do_int_id ) { + // Register int_id class under given name + sol::usertype ut = luna::new_usertype( lua, luna::no_bases, luna::constructors < + IID(), + IID( const IID & ), + IID( const SID & ) + > () + ); + + luna::set_fx( ut, "obj", []( const IID & iid ) -> const T* { + return &iid.obj(); + } ); + luna::set_fx( ut, "str_id", &IID::id ); + luna::set_fx( ut, "is_valid", &IID::is_valid ); + luna::set_fx( ut, sol::meta_function::to_string, []( const IID & id ) -> std::string { + return string_format( "%s[%d][%s]", luna::detail::luna_traits::name, id.to_i(), id.is_valid() ? id.id().c_str() : "" ); + } ); + } +} + +void cata::detail::reg_game_ids( sol::state &lua ) +{ + // Don't forget to define comparison operators for your target type! + // Some already may have them, but for the rest you can do it + // with LUA_TYPE_OPS macro. + + reg_id( lua ); + reg_id( lua ); + reg_id( lua ); + reg_id( lua ); + reg_id( lua ); + reg_id( lua ); + reg_id( lua ); +} + +void cata::detail::reg_types( sol::state &lua ) +{ + { + sol::usertype ut = + luna::new_usertype( lua, luna::no_bases, luna::no_constructor ); + + luna::set_fx( ut, "str_id", []( const faction & x ) -> faction_id { + return x.id; + } ); + + // Factions are a pain because they _inherit_ from their type, not reference it by id. + // This causes various weirdness, so let's omit the fields for now. + } + { + sol::usertype ut = + luna::new_usertype( lua, luna::no_bases, luna::no_constructor ); + + luna::set_fx( ut, "str_id", []( const ter_t & x ) -> ter_str_id { + return x.id; + } ); + luna::set_fx( ut, "int_id", []( const ter_t & x ) -> ter_id { + return x.id.id(); + } ); + + luna::set( ut, "open", &ter_t::open ); + luna::set( ut, "close", &ter_t::close ); + luna::set( ut, "trap_id_str", &ter_t::trap_id_str ); + luna::set( ut, "transforms_into", &ter_t::transforms_into ); + luna::set( ut, "roof", &ter_t::roof ); + luna::set( ut, "heat_radiation", &ter_t::heat_radiation ); + } + { + sol::usertype ut = + luna::new_usertype( lua, luna::no_bases, luna::no_constructor ); + + luna::set_fx( ut, "str_id", []( const furn_t &x ) -> furn_str_id { + return x.id; + } ); + luna::set_fx( ut, "int_id", []( const furn_t &x ) -> furn_id { + return x.id.id(); + } ); + + luna::set( ut, "open", &furn_t::open ); + luna::set( ut, "close", &furn_t::close ); + luna::set( ut, "transforms_into", &furn_t::transforms_into ); + } +} + +#endif diff --git a/src/catalua_bindings_utils.h b/src/catalua_bindings_utils.h new file mode 100644 index 000000000000..82313bb2829a --- /dev/null +++ b/src/catalua_bindings_utils.h @@ -0,0 +1,17 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_BINDINGS_UTILS_H +#define CATA_SRC_CATALUA_BINDINGS_UTILS_H + +#include "catalua_luna.h" +#include "json.h" + +template +void reg_serde_functions( sol::usertype &ut ) +{ + luna::set_fx( ut, "serialize", sol::resolve< void( JsonOut & ) const >( &T::serialize ) ); + luna::set_fx( ut, "deserialize", sol::resolve< void( JsonIn & ) >( &T::deserialize ) ); +} + +#define DOC( x ) luna::doc( x ) + +#endif // CATA_SRC_CATALUA_BINDINGS_UTILS_H diff --git a/src/catalua_console.cpp b/src/catalua_console.cpp new file mode 100644 index 000000000000..d93aaf94edd1 --- /dev/null +++ b/src/catalua_console.cpp @@ -0,0 +1,300 @@ +#if defined(LUA) + +#include "catalua_console.h" + +#include "catalua_log.h" +#include "catalua_impl.h" +#include "cursesdef.h" +#include "game.h" +#include "init.h" +#include "input.h" +#include "output.h" +#include "string_editor_window.h" +#include "string_utils.h" +#include "ui_manager.h" +#include "uistate.h" + +namespace cata +{ + +struct folded_log_msg { + bool is_head = false; + LuaLogLevel level; + std::string text; +}; + +static std::vector build_folded_log( int width ) +{ + std::vector ret; + for( const lua_log_msg &msg : get_lua_log_instance().get_entries() ) { + std::vector lines = foldstring( msg.text, width ); + for( int i = static_cast( lines.size() ) - 1; i >= 0; i-- ) { + ret.push_back( folded_log_msg{ i == 0, msg.level, std::move( lines[i] ) } ); + } + } + return ret; +} + +static nc_color get_log_level_color( LuaLogLevel level ) +{ + switch( level ) { + case LuaLogLevel::Input: + return c_white; + case LuaLogLevel::DebugMsg: + return c_magenta; + case LuaLogLevel::Error: + return c_red; + case LuaLogLevel::Warn: + return c_yellow; + case LuaLogLevel::Info: + return c_light_gray; + default: + debugmsg( "Log level color not defined!" ); + return c_white; + } +} + +static std::vector &get_input_history() +{ + return uistate.gethistory( "LUA_CONSOLE" ); +} + +static int num_history_entries() +{ + return static_cast( get_input_history().size() ); +} + +static void add_to_input_history( const std::string &s ) +{ + std::vector &hist = get_input_history(); + for( auto it = hist.begin(); it != hist.end(); it++ ) { + if( *it == s ) { + // Refresh existing history entry + std::string msg = std::move( *it ); + hist.erase( it ); + hist.push_back( std::move( msg ) ); + return; + } + } + // Add new history entry + hist.push_back( s ); +} + +void show_lua_console_impl() +{ + input_context ctxt( "LUA_CONSOLE" ); + ctxt.register_action( "HELP_KEYBINDINGS" ); + ctxt.register_action( "EDIT" ); + ctxt.register_action( "QUIT" ); + ctxt.register_action( "LUA_RELOAD" ); + ctxt.register_action( "HISTORY_UP" ); + ctxt.register_action( "HISTORY_DOWN" ); + ctxt.register_action( "SCROLL_UP" ); + ctxt.register_action( "SCROLL_DOWN" ); + ctxt.register_action( "SCROLL_TOP" ); + ctxt.register_action( "SCROLL_BOTTOM" ); + + ui_adaptor ui; + + constexpr int CURRENT_INPUT = -1; + constexpr int scroll_speed = 5; + constexpr int input_area_size = 5; + + point win_pos; + point win_size; + point log_pos; + point log_size; + point prompt_pos; + point prompt_size; + + int log_scroll_pos = 0; + std::vector log_folded; + + const auto create_string_editor = [&]() { + // Offset by one for the scrollbar + return catacurses::newwin( prompt_size.y, prompt_size.x + 1, prompt_pos - point( 1, 0 ) ); + }; + + catacurses::window w_console; + catacurses::window w_log; + catacurses::window w_prompt; + + std::string current_input; + int history_cursor = CURRENT_INPUT; + + bool is_editing = false; + + ui.on_screen_resize( [&]( ui_adaptor & ui ) { + win_size = point( TERMX, TERMY ); + win_pos = point( ( TERMX - win_size.x ) / 2, ( TERMY - win_size.y ) / 2 ); + prompt_size = point( win_size.x - 3, input_area_size ); + prompt_pos = win_pos + point( 2, win_size.y - input_area_size - 1 ); + log_pos = win_pos + point( 1, 1 ); + log_size = point( win_size.x - 2, win_size.y - input_area_size - 7 ); + w_console = catacurses::newwin( win_size.y, win_size.x, win_pos ); + w_log = catacurses::newwin( log_size.y, log_size.x, log_pos ); + w_prompt = catacurses::newwin( prompt_size.y, prompt_size.x, prompt_pos ); + ui.position_from_window( w_console ); + } ); + ui.mark_resize(); + + ui.on_redraw( [&]( const ui_adaptor & ) { + werase( w_console ); + draw_border( w_console ); + std::string separator; + int separator_y = win_size.y - prompt_size.y - 2; + for( int i = 0; i < win_size.x - 2; i++ ) { + separator += LINE_OXOX_S; + } + mvwprintz( w_console, point( 1, separator_y ), c_light_gray, separator ); + mvwprintz( w_console, point( 1, separator_y - 4 ), c_light_gray, separator ); + if( is_editing ) { + mvwprintz( w_console, point( 1, separator_y - 3 ), c_light_gray, + _( "Press Ctrl+S to run script, press Esc to cancel" ) + ); + mvwprintz( w_console, point( 1, separator_y - 2 ), c_light_gray, + _( "Press arrow keys to navigate text input" ) + ); + mvwprintz( w_console, point( 1, separator_y - 1 ), c_light_gray, + _( "Press Enter to add new line" ) + ); + } else { + mvwprintz( w_console, point( 1, separator_y - 3 ), c_light_gray, + _( "Press Enter to enter/edit command, Esc to quit" ) + ); + mvwprintz( w_console, point( 1, separator_y - 2 ), c_light_gray, + _( "Press Up/Down arrows to select from history" ) + ); + mvwprintz( w_console, point( 1, separator_y - 1 ), c_light_gray, + _( "Press PgUp/PgDn/Home/End to scroll output window" ) + ); + } + + scrollbar() + .offset_x( 0 ) + .offset_y( 1 ) + .content_size( log_folded.size() ) + .viewport_size( log_size.y ) + .viewport_pos( static_cast( log_folded.size() ) - log_scroll_pos - log_size.y ) + .scroll_to_last( false ) + .apply( w_console ); + + wnoutrefresh( w_console ); + + werase( w_log ); + + int y_pos = log_size.y - 1; + int start_line = log_scroll_pos; + int end_line = std::min( static_cast( log_folded.size() ), start_line + log_size.y ); + for( int log_line = start_line; log_line < end_line; log_line++ ) { + const folded_log_msg &msg = log_folded[log_line]; + nc_color col = get_log_level_color( msg.level ); + int x_pos = 1; + if( msg.level == LuaLogLevel::Input ) { + // User input is indented, and first line is highlighted + x_pos = 2; + if( msg.is_head ) { + mvwprintz( w_log, point( 1, y_pos ), col, ">" ); + } + } + mvwprintz( w_log, point( x_pos, y_pos ), col, msg.text ); + y_pos--; + } + + wnoutrefresh( w_log ); + + werase( w_prompt ); + + print_scrollable( + w_prompt, + 0, + history_cursor == CURRENT_INPUT ? current_input : get_input_history()[history_cursor], + c_light_gray, + "" + ); + + wnoutrefresh( w_prompt ); + } ); + + bool log_invalidated = true; + while( true ) { + if( log_invalidated ) { + log_invalidated = false; + log_scroll_pos = 0; + log_folded = build_folded_log( 76 ); + } + ui_manager::redraw_invalidated(); + + const std::string act = ctxt.handle_input(); + + if( act == "QUIT" ) { + // Close + return; + } else if( act == "HISTORY_UP" ) { + int sz = num_history_entries(); + if( sz != 0 && history_cursor != 0 ) { + if( history_cursor == CURRENT_INPUT ) { + history_cursor = sz - 1; + } else { + history_cursor = std::max( 0, history_cursor - 1 ); + } + } + // Update input preview + ui.invalidate_ui(); + } else if( act == "HISTORY_DOWN" ) { + int sz = num_history_entries(); + if( sz != 0 && history_cursor != CURRENT_INPUT ) { + if( history_cursor == sz - 1 ) { + history_cursor = CURRENT_INPUT; + } else { + history_cursor = std::min( history_cursor + 1, sz - 1 ); + } + } + // Update input preview + ui.invalidate_ui(); + } else if( act == "SCROLL_UP" || act == "SCROLL_TOP" ) { + int limit = std::max( 0, static_cast( log_folded.size() ) - log_size.y ); + if( act == "SCROLL_TOP" ) { + log_scroll_pos = limit; + } else { + log_scroll_pos = std::min( limit, log_scroll_pos + scroll_speed ); + } + ui.invalidate_ui(); + } else if( act == "SCROLL_DOWN" ) { + log_scroll_pos = std::max( 0, log_scroll_pos - scroll_speed ); + ui.invalidate_ui(); + } else if( act == "SCROLL_BOTTOM" ) { + log_scroll_pos = 0; + ui.invalidate_ui(); + } else if( act == "EDIT" ) { + // Edit + is_editing = true; + ui.invalidate_ui(); + string_editor_window ew( + create_string_editor, + history_cursor == CURRENT_INPUT ? current_input : get_input_history()[history_cursor] + ); + std::pair res = ew.query_string(); + is_editing = false; + history_cursor = CURRENT_INPUT; + if( res.first ) { + // Confirmed + current_input.clear(); + add_to_input_history( res.second ); + log_invalidated = true; + run_console_input( DynamicDataLoader::get_instance().lua->lua, res.second ); + } else { + // Canceled, save input for later use + current_input = res.second; + } + } else if( act == "LUA_RELOAD" ) { + ui.invalidate_ui(); + log_invalidated = true; + reload_lua_code(); + } + } +} + +} // namespace cata + +#endif // LUA diff --git a/src/catalua_console.h b/src/catalua_console.h new file mode 100644 index 000000000000..9378ab8f29b4 --- /dev/null +++ b/src/catalua_console.h @@ -0,0 +1,12 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_CONSOLE_H +#define CATA_SRC_CATALUA_CONSOLE_H + +namespace cata +{ + +void show_lua_console_impl(); + +} // namespace cata + +#endif // CATA_SRC_CATALUA_CONSOLE_H \ No newline at end of file diff --git a/src/catalua_impl.cpp b/src/catalua_impl.cpp new file mode 100644 index 000000000000..0db4491f5ab2 --- /dev/null +++ b/src/catalua_impl.cpp @@ -0,0 +1,120 @@ +#ifdef LUA +#include "catalua_impl.h" + +#include "catalua_bindings.h" +#include "catalua_log.h" +#include "catalua_sol.h" +#include "debug.h" +#include "string_formatter.h" + +sol::state make_lua_state() +{ + sol::state lua; + + lua.open_libraries( + sol::lib::base, + sol::lib::math, + sol::lib::string, + sol::lib::table + ); + + cata::reg_all_bindings( lua ); + + return lua; +} + +void run_lua_script( sol::state &lua, const std::string &script_name ) +{ + sol::load_result load_res = lua.load_file( script_name ); + + if( !load_res.valid() ) { + sol::error err = load_res; + throw std::runtime_error( + string_format( "Failed to load script %s: %s", script_name, err.what() ) + ); + } + + sol::protected_function exec = load_res; + + // Sandboxing: create environment that uses globals table as fallback + // to prevent script from accidentally (or intentionally) modifying globals table. + // All modifications will be stored in an environment which then gets discarded. + sol::environment my_env( lua, sol::create, lua.globals() ); + sol::set_environment( my_env, exec ); + + sol::protected_function_result exec_res = exec(); + + if( !exec_res.valid() ) { + sol::error err = exec_res; + throw std::runtime_error( + string_format( "Script runtime error in %s: %s", script_name, err.what() ) + ); + } +} + +void run_console_input( sol::state &lua, const std::string &chunk ) +{ + DebugLog( DL::Info, DC::Lua ) << "CONSOLE: " << chunk; + cata::get_lua_log_instance().add( + cata::LuaLogLevel::Input, + std::string( chunk ) + ); + + sol::load_result load_res = lua.load( chunk, "console input" ); + + if( !load_res.valid() ) { + // No need to use obnoxious debugmsgs, user will see the error in log + sol::error err = load_res; + cata::get_lua_log_instance().add( + cata::LuaLogLevel::Error, + string_format( "Failed to load: %s", err.what() ) + ); + return; + } + + sol::protected_function exec = load_res; + + // No sandboxing here, we trust console user :) + + sol::protected_function_result exec_res = exec(); + + if( !exec_res.valid() ) { + // No need to use obnoxious debugmsgs, user will see the error in log + sol::error err = exec_res; + cata::get_lua_log_instance().add( + cata::LuaLogLevel::Error, + string_format( "Runtime error: %s", err.what() ) + ); + return; + } + + try { + sol::object retval = exec_res; + if( retval == sol::nil ) { + // No return - don't spam + return; + } + std::string val = lua["tostring"]( retval ); + cata::get_lua_log_instance().add( + cata::LuaLogLevel::Info, + string_format( "# %s", val ) + ); + } catch( std::runtime_error &e ) { + cata::get_lua_log_instance().add( + cata::LuaLogLevel::Info, + string_format( "# ??? %s", e.what() ) + ); + } +} + +void check_func_result( sol::protected_function_result &res ) +{ + if( !res.valid() ) { + sol::error err = res; + throw std::runtime_error( + string_format( "Script runtime error: %s", err.what() ) + ); + } +} + +#endif diff --git a/src/catalua_impl.h b/src/catalua_impl.h new file mode 100644 index 000000000000..b9a80ea79222 --- /dev/null +++ b/src/catalua_impl.h @@ -0,0 +1,34 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_IMPL_H +#define CATA_SRC_CATALUA_IMPL_H + +#include "calendar.h" +#include "catalua_sol.h" + +namespace cata +{ +struct on_every_x_hooks { + time_duration interval; + std::vector functions; +}; + +/** + * Lua state handle. + * Definition is hidden from outside code to prevent sol::state + * usage and visibility outside catalua files. + */ +struct lua_state { + sol::state lua; + + lua_state() = default; + ~lua_state() = default; +}; + +} // namespace cata + +sol::state make_lua_state(); +void run_lua_script( sol::state &lua, const std::string &script_name ); +void run_console_input( sol::state &lua, const std::string &chunk ); +void check_func_result( sol::protected_function_result &res ); + +#endif // CATA_SRC_CATALUA_IMPL_H diff --git a/src/catalua_iuse_actor.cpp b/src/catalua_iuse_actor.cpp new file mode 100644 index 000000000000..a4dc8ae3ad07 --- /dev/null +++ b/src/catalua_iuse_actor.cpp @@ -0,0 +1,47 @@ +#if defined(LUA) + +#include "catalua_iuse_actor.h" + +#include "catalua_impl.h" +#include "player.h" + +lua_iuse_actor::lua_iuse_actor( const std::string &type, sol::protected_function &&luafunc ) + : iuse_actor( type ), luafunc( luafunc ) {} + +lua_iuse_actor::~lua_iuse_actor() = default; + +void lua_iuse_actor::load( const JsonObject & ) +{ + // TODO: custom data +} + +int lua_iuse_actor::use( player &who, item &itm, bool tick, const tripoint &pos ) const +{ + if( !tick ) { + try { + sol::protected_function_result res = luafunc( who.as_character(), itm, pos ); + check_func_result( res ); + int ret = res; + return ret; + } catch( std::runtime_error &e ) { + debugmsg( "Failed to run iuse_function k='%s': %s", type, e.what() ); + } + } else { + // TODO: ticking use + } + return 1; +} + +ret_val lua_iuse_actor::can_use( const Character &, const item &, bool, + const tripoint & ) const +{ + // TODO: check if can use + return ret_val::make_success(); +} + +std::unique_ptr lua_iuse_actor::clone() const +{ + return std::make_unique( *this ); +} + +#endif // LUA diff --git a/src/catalua_iuse_actor.h b/src/catalua_iuse_actor.h new file mode 100644 index 000000000000..b9ae0fbdabc7 --- /dev/null +++ b/src/catalua_iuse_actor.h @@ -0,0 +1,24 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_IUSE_ACTOR_H +#define CATA_SRC_CATALUA_IUSE_ACTOR_H + +#include "iuse.h" +#include "catalua_sol.h" +#include "ret_val.h" + +/** Dynamic iuse_actor provided by Lua. */ +class lua_iuse_actor : public iuse_actor +{ + private: + sol::protected_function luafunc; + + public: + lua_iuse_actor( const std::string &type, sol::protected_function &&luafunc ); + ~lua_iuse_actor() override; + void load( const JsonObject &obj ) override; + int use( player &who, item &itm, bool tick, const tripoint &pos ) const override; + ret_val can_use( const Character &, const item &, bool, const tripoint & ) const override; + std::unique_ptr clone() const override; +}; + +#endif // CATA_SRC_CATALUA_IUSE_ACTOR_H diff --git a/src/catalua_log.cpp b/src/catalua_log.cpp new file mode 100644 index 000000000000..1f4f19f77481 --- /dev/null +++ b/src/catalua_log.cpp @@ -0,0 +1,43 @@ +#if defined(LUA) +#include "catalua_log.h" + +namespace cata +{ + +lua_log_handler::lua_log_handler() +{ + set_log_capacity( DEFAULT_LUA_LOG_CAPACITY ); +} + +void lua_log_handler::set_log_capacity( size_t lines ) +{ + if( lines < entries.size() ) { + // Will erase old entries + entries.resize( lines ); + } + capacity = lines; +} + +void lua_log_handler::add( LuaLogLevel level, std::string &&text ) +{ + while( entries.size() >= capacity ) { + entries.pop_back(); + } + entries.push_front( lua_log_msg{ level, text } ); +} + +void lua_log_handler::clear() +{ + entries.clear(); +} + +lua_log_handler &get_lua_log_instance() +{ + static lua_log_handler log; + return log; +} + +} // namespace cata + +#endif + diff --git a/src/catalua_log.h b/src/catalua_log.h new file mode 100644 index 000000000000..fcfebe23cc1c --- /dev/null +++ b/src/catalua_log.h @@ -0,0 +1,51 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_LOG_H +#define CATA_SRC_CATALUA_LOG_H + +#include +#include + +namespace cata +{ + +constexpr size_t DEFAULT_LUA_LOG_CAPACITY = 100; + +enum class LuaLogLevel { + Input, + Info, + Warn, + Error, + DebugMsg, +}; + +struct lua_log_msg { + LuaLogLevel level; + std::string text; +}; + +class lua_log_handler +{ + public: + lua_log_handler(); + ~lua_log_handler() = default; + + void set_log_capacity( size_t lines ); + + void add( LuaLogLevel level, std::string &&text ); + + void clear(); + + inline const std::deque &get_entries() const { + return entries; + } + + private: + std::deque entries; + size_t capacity = 0; +}; + +lua_log_handler &get_lua_log_instance(); + +} // namespace cata + +#endif // CATA_SRC_CATALUA_LOG_H diff --git a/src/catalua_luna.h b/src/catalua_luna.h new file mode 100644 index 000000000000..b70165b8fb2d --- /dev/null +++ b/src/catalua_luna.h @@ -0,0 +1,606 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_LUNA_H +#define CATA_SRC_CATALUA_LUNA_H + +#include +#include +#include +#include +#include + +#include "catalua_sol.h" +#include "catalua_readonly.h" +#include "debug.h" +#include "string_formatter.h" + +#define LUNA_VAL( Class, Name ) \ + namespace luna::detail { \ + template<> \ + struct luna_traits { \ + constexpr static bool impl = true; \ + constexpr static std::string_view name = Name; \ + }; \ + } // namespace luna::detail + +#define LUNA_DOC( Class, Name ) LUNA_VAL( Class, Name ) + +#define LUNA_ID( Class, Name ) \ + LUNA_DOC( Class, Name "Raw" ) \ + LUNA_VAL( string_id, Name "Id" ) \ + LUNA_VAL( int_id, Name "IntId" ) + +#define LUNA_ENUM( Class, Name ) LUNA_VAL( Class, Name ) + +namespace luna +{ + +struct no_bases_t {}; +constexpr static no_bases_t no_bases; + +template +using bases = sol::bases; + +constexpr sol::no_construction no_constructor; + +template +using constructors = sol::constructors; + +namespace detail +{ + +constexpr std::string_view KEY_TYPES = "#types"; +constexpr std::string_view KEY_ENUMS = "#enums"; +constexpr std::string_view KEY_LIBS = "#libs"; +constexpr std::string_view KEY_LIB_IMPL = "#lib_impl"; +constexpr std::string_view KEY_LIB_COMMENT = "lib_comment"; +constexpr std::string_view KEY_ENUM_ENTRIES = "entries"; +constexpr std::string_view KEY_TYPE_IMPL = "#type_impl"; +constexpr std::string_view KEY_DOCTABLE = "catadoc"; +constexpr std::string_view KEY_BASES = "#bases"; +constexpr std::string_view KEY_CONSTRUCT = "#construct"; +constexpr std::string_view KEY_MEMBER = "#member"; +constexpr std::string_view KEY_MEMBER_TYPE = "type"; +constexpr std::string_view KEY_MEMBER_COMMENT = "comment"; +constexpr std::string_view KEY_MEMBER_VARIABLE_TYPE = "vartype"; +constexpr std::string_view KEY_MEMBER_VARIABLE_HAS_VALUE = "hasval"; +constexpr std::string_view KEY_MEMBER_VARIABLE_VALUE = "varval"; +constexpr std::string_view KEY_MEMBER_ARGS = "args"; +constexpr std::string_view KEY_MEMBER_OVERLOADS = "overloads"; +constexpr std::string_view KEY_MEMBER_RETVAL = "retval"; +constexpr std::string_view KEY_MEMBER_NAME = "name"; +constexpr std::string_view KEY_GET_TYPE = "get_luna_type"; +constexpr std::string_view KEY_USERTYPE_COMMENT = "type_comment"; + +constexpr std::string_view MEMBER_IS_VAR = "var"; +constexpr std::string_view MEMBER_IS_FUNC = "func"; +constexpr std::string_view MEMBER_IS_CONST_FUNC = "const_func"; + +template +struct luna_traits { + constexpr static bool impl = false; + constexpr static std::string_view name = ""; +}; + +extern std::string_view current_comment; + +template +using remove_cv_ref_t = typename std::remove_cv::type>::type; + +template +using fx_traits = sol::meta::meta_detail::fx_traits; + +inline void add_comment( sol::table &dt, std::string_view key ) +{ + if( !current_comment.empty() ) { + dt[key] = current_comment; + current_comment = ""; + } +} + +template +std::string doc_value_impl() +{ + //static_assert(luna_traits::impl, "Type must implement luna_traits" ); + if constexpr( luna_traits::impl ) { + return std::string( luna_traits::name ); + } else { + using ValNoPtr = typename std::remove_pointer::type; + using ValBare = remove_cv_ref_t; + if constexpr( luna_traits::impl ) { + return std::string( luna_traits::name ); + } else { + return std::string( ""; + } + } +} + +template +std::string doc_value( sol::types ); + +template +std::string doc_value( sol::types> ) +{ + std::string ret = "("; + bool is_first = true; + ( [&]() { + if( is_first ) { + is_first = false; + } else { + ret += ","; + } + ret += " "; + ret += doc_value( sol::types() ); + } + (), ... ); + if( !is_first ) { + ret += " "; + } + return ret + ")"; +} + +template +std::string doc_value( sol::types> ) +{ + std::string ret = "Opt("; + ret += doc_value( sol::types() ); + return ret + ")"; +} + +template +std::string doc_value( sol::types ) +{ + return doc_value_impl(); +} + +template +std::vector doc_arg_list() +{ + std::vector ret; + + ( ( + ret.push_back( + doc_value( sol::types() ) ) + ), ... ); + + return ret; +} + +template +std::vector doc_one_constructor( std::function ) +{ + return doc_arg_list(); +} + +template +void doc_constructors( sol::table &dt, const sol::constructor_list & ) +{ + std::vector> ctors; + + ( ( + ctors.push_back( doc_one_constructor( std::function( nullptr ) ) ) + ), ... ); + + dt[KEY_CONSTRUCT] = ctors; +} + +inline void doc_constructors( sol::table &dt, const sol::no_construction & ) +{ + std::vector> ctors; + dt[KEY_CONSTRUCT] = ctors; +} + +template +void doc_bases( sol::table &dt, const sol::bases & ) +{ + std::vector bases; + + ( ( + bases.push_back( doc_value( sol::types() ) ) + ), ... ); + + dt[KEY_BASES] = bases; +} + +inline void doc_bases( sol::table &dt, const no_bases_t & ) +{ + std::vector ctors; + dt[KEY_BASES] = ctors; +} + +inline sol::table get_global_doctable( sol::state_view &lua ) +{ + sol::object obj = lua[detail::KEY_DOCTABLE]; + if( obj.valid() ) { + return obj; + } else { + sol::table dt = lua.create_table(); + dt[detail::KEY_TYPES] = lua.create_table(); + dt[detail::KEY_ENUMS] = lua.create_table(); + dt[detail::KEY_LIBS] = lua.create_table(); + lua[detail::KEY_DOCTABLE] = dt; + return dt; + } +} + +template +inline sol::table get_type_doctable( sol::state_view &lua ) +{ + static_assert( detail::luna_traits::impl, "Type must implement luna_traits" ); + + sol::table gdt = get_global_doctable( lua ); + return gdt[detail::KEY_TYPES][detail::luna_traits::name]; +} + +template +inline sol::table get_enum_doctable( sol::state_view &lua ) +{ + static_assert( detail::luna_traits::impl, "Type must implement luna_traits" ); + + sol::table gdt = get_global_doctable( lua ); + return gdt[detail::KEY_ENUMS][detail::luna_traits::name]; +} + +template +void doc_member( sol::table &dt, sol::types && ) +{ + dt[KEY_MEMBER_TYPE] = MEMBER_IS_VAR; + add_comment( dt, KEY_MEMBER_COMMENT ); + dt[KEY_MEMBER_VARIABLE_TYPE] = doc_value( sol::types() ); +} + +template +void doc_member_fx_impl2( sol::table &dt, sol::types &&, sol::types && ) +{ + dt[KEY_MEMBER_RETVAL] = doc_value( sol::types() ); + if constexpr( add_self_arg ) { + dt[KEY_MEMBER_ARGS] = doc_arg_list(); + } else { + dt[KEY_MEMBER_ARGS] = doc_arg_list(); + } +} + +template +void doc_member_fx_overload( sol::table &dt, std::vector &overloads ) +{ + sol::state_view lua( dt.lua_state() ); + sol::table overload = lua.create_table(); + overloads.push_back( overload ); + using RetVal = typename fx_traits::return_type; + using Args = typename fx_traits::args_list; + constexpr bool add_self_arg = !fx_traits::is_member_function; + doc_member_fx_impl2( overload, sol::types(), Args() ); +} + +template +void doc_member_fx_impl( sol::table &dt, sol::types && ) +{ + dt[KEY_MEMBER_TYPE] = MEMBER_IS_FUNC; + add_comment( dt, KEY_MEMBER_COMMENT ); + std::vector overloads; + + ( [&]() { + doc_member_fx_overload( dt, overloads ); + } + (), ... ); + dt[KEY_MEMBER_OVERLOADS] = overloads; +} + +template +void doc_member_fx( sol::table &dt, sol::types> && ) +{ + doc_member_fx_impl( dt, sol::types() ); +} + +template +void doc_member_fx( sol::table &dt, sol::types && ) +{ + doc_member_fx_impl( dt, sol::types() ); +} + +template +void doc_free( sol::table &dt, Value val ) +{ + dt[KEY_MEMBER_TYPE] = MEMBER_IS_VAR; + add_comment( dt, KEY_MEMBER_COMMENT ); + dt[KEY_MEMBER_VARIABLE_TYPE] = doc_value( sol::types() ); + dt[KEY_MEMBER_VARIABLE_HAS_VALUE] = true; + dt[KEY_MEMBER_VARIABLE_VALUE] = val; +} + +template +void doc_free_fx_impl2( sol::table &dt, sol::types &&, sol::types && ) +{ + dt[KEY_MEMBER_RETVAL] = doc_value( sol::types() ); + dt[KEY_MEMBER_ARGS] = doc_arg_list(); +} + +template +void doc_free_fx_overload( sol::table &dt, std::vector &overloads ) +{ + sol::state_view lua( dt.lua_state() ); + sol::table overload = lua.create_table(); + overloads.push_back( overload ); + using RetVal = typename fx_traits::return_type; + using Args = typename fx_traits::args_list; + doc_free_fx_impl2( overload, sol::types(), Args() ); +} + +template +void doc_free_fx_impl( sol::table &dt, sol::types && ) +{ + dt[KEY_MEMBER_TYPE] = MEMBER_IS_FUNC; + add_comment( dt, KEY_MEMBER_COMMENT ); + std::vector overloads; + ( [&]() { + doc_free_fx_overload( dt, overloads ); + } + (), ... ); + dt[KEY_MEMBER_OVERLOADS] = overloads; +} + +template +void doc_free_fx( sol::table &dt, sol::types> && ) +{ + doc_free_fx_impl( dt, sol::types() ); +} + +template +void doc_free_fx( sol::table &dt, sol::types && ) +{ + doc_free_fx_impl( dt, sol::types() ); +} + +template +sol::table make_type_member_doctable( sol::table type_dt, const Key &key ) +{ + sol::state_view lua( type_dt.lua_state() ); + std::vector &members = type_dt[ detail::KEY_MEMBER ]; + sol::table member_dt = lua.create_table(); + member_dt[detail::KEY_MEMBER_NAME] = key; + members.push_back( member_dt ); + return member_dt; +} + +} // namespace detail + +template +sol::usertype new_usertype( + sol::state_view &lua, + Bases &&bases, + ConstructorScheme &&constructor +) +{ + static_assert( detail::luna_traits::impl, "Type must implement luna_traits" ); + + // Ensure global doctable exists + sol::table global_dt = detail::get_global_doctable( lua ); + + constexpr std::string_view name = detail::luna_traits::name; + + // Register Sol usertype + sol::usertype ut; + using BasesBare = detail::remove_cv_ref_t; + if constexpr( std::is_same_v ) { + ut = lua.new_usertype( name, constructor ); + } else { + ut = lua.new_usertype( name, constructor, sol::base_classes, bases ); + } + + // Create doctable for this type + sol::table type_dt = lua.create_table(); + global_dt[detail::KEY_TYPES][name] = type_dt; + + // Link relevant Sol usertype in docs + type_dt[detail::KEY_TYPE_IMPL] = ut; + + // Doc comment + detail::add_comment( type_dt, detail::KEY_USERTYPE_COMMENT ); + + // Init members table + type_dt[detail::KEY_MEMBER] = std::vector(); + + // Document constructors (or lack thereof) + detail::doc_constructors( type_dt, constructor ); + + // Document bases (or lack thereof) + detail::doc_bases( type_dt, bases ); + + // Add helper method to get name under which usertype is bound in Lua + ut[detail::KEY_GET_TYPE] = []() -> std::string_view { + return detail::luna_traits::name; + }; + + return ut; +} + +template +void set_fx( + sol::usertype &ut, + Key &&key, + Func value +) +{ + // Due to a bug in sol2, on GCC build protected function call may call wrong lambda + // https://github.com/ThePhD/sol2/issues/1444 + // This happens if we register with table.set( key, func ), but for + // some reason table[key] = func makes it work fine. + ut[ key ] = std::forward( value ); + + sol::state_view lua( ut.lua_state() ); + sol::table type_dt = detail::get_type_doctable( lua ); + sol::table member_dt = detail::make_type_member_doctable( type_dt, key ); + detail::doc_member_fx( member_dt, sol::types() ); +} + +template +void set( + sol::usertype &ut, + Key &&key, + Value &&value +) +{ + ut[ key ] = std::forward( value ); + + sol::state_view lua( ut.lua_state() ); + sol::table type_dt = detail::get_type_doctable( lua ); + sol::table member_dt = detail::make_type_member_doctable( type_dt, key ); + detail::doc_member( member_dt, sol::types() ); +} + +template +struct userenum { + sol::table t; + bool finalized = false; + + inline ~userenum() { + if( !finalized ) { + debugmsg( "Userenum<%s> has not been finalized!", detail::luna_traits::name ); + std::abort(); + } + } +}; + +template +userenum begin_enum( + sol::state_view &lua +) +{ + static_assert( detail::luna_traits::impl, "Type must implement luna_traits" ); + + sol::table ut = lua.create_table(); + return userenum { ut }; +} + +template +void add_val( + userenum &e, + const Key &key, + const Enum &value +) +{ + e.t[key] = value; +} + +template +void finalize_enum( + userenum &e +) +{ + sol::state_view lua( e.t.lua_state() ); + constexpr std::string_view name = detail::luna_traits::name; + + // Ensure global doctable exists + sol::table global_dt = detail::get_global_doctable( lua ); + + // Create doctable for this enum + sol::table enum_dt = lua.create_table(); + global_dt[detail::KEY_ENUMS][name] = enum_dt; + + // Link to original list of entries + enum_dt[detail::KEY_ENUM_ENTRIES] = e.t; + + // Make read-only so Lua code doesn't mess with it + sol::table et = cata::make_readonly_table( + lua, e.t, + string_format( "Tried to modify enum table %s.", name ) + ); + lua.globals()[name] = et; + e.finalized = true; +} + +struct userlib { + sol::table t; + std::string_view name; + sol::table dt; + bool finalized = false; + + inline ~userlib() { + if( !finalized ) { + debugmsg( "Userlib has not been finalized!" ); + std::abort(); + } + } +}; + +inline userlib begin_lib( + sol::state_view &lua, + std::string_view name +) +{ + // Ensure global doctable exists + sol::table global_dt = detail::get_global_doctable( lua ); + + // Create doctable for this lib + sol::table lib_dt = lua.create_table(); + global_dt[detail::KEY_LIBS][name] = lib_dt; + + // Init members table + lib_dt[detail::KEY_MEMBER] = std::vector(); + + // Library comment + detail::add_comment( lib_dt, detail::KEY_LIB_COMMENT ); + + // Create library itself + sol::table t = lua.create_table(); + + // Link to original library from docs + lib_dt[detail::KEY_LIB_IMPL] = t; + + return userlib { t, name, lib_dt }; +} + +template +void set_fx( + userlib &lib, + Key &&key, + Func value +) +{ + // Due to a bug in sol2, on GCC build protected function call may call wrong lambda + // https://github.com/ThePhD/sol2/issues/1444 + // This happens if we register with table.set( key, func ), but for + // some reason table[key] = func makes it work fine. + lib.t[ key ] = std::forward( value ); + + sol::state_view lua( lib.t.lua_state() ); + sol::table member_dt = detail::make_type_member_doctable( lib.dt, key ); + detail::doc_free_fx( member_dt, sol::types() ); +} + +template +void set( + userlib &lib, + Key &&key, + Value &&value +) +{ + lib.t[ key ] = value; + + sol::state_view lua( lib.t.lua_state() ); + sol::table member_dt = detail::make_type_member_doctable( lib.dt, key ); + detail::doc_free( member_dt, value ); +} + +inline void finalize_lib( + userlib &lib +) +{ + sol::state_view lua( lib.t.lua_state() ); + + // Make read-only so Lua code doesn't mess with it + sol::table et = cata::make_readonly_table( + lua, lib.t, + string_format( "Tried to modify library %s.", lib.name ) + ); + lua.globals()[lib.name] = et; + lib.finalized = true; +} + +inline void doc( std::string_view doc ) +{ + detail::current_comment = doc; +} + +} // namespace luna + +#endif // CATA_SRC_CATALUA_LUNA_H diff --git a/src/catalua_luna_doc.h b/src/catalua_luna_doc.h new file mode 100644 index 000000000000..31af5e440dbd --- /dev/null +++ b/src/catalua_luna_doc.h @@ -0,0 +1,89 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_LUNA_DOC_H +#define CATA_SRC_CATALUA_LUNA_DOC_H + +#include "catalua_luna.h" +#include "type_id.h" + +enum color_id : int; +enum game_message_type : int; + +class avatar; +class Character; +class Creature; +class distribution_grid_tracker; +class distribution_grid; +class effect_type; +class item_stack; +class item; +class map_stack; +class map; +class monster; +class npc; +class player; +class query_popup; +class time_duration; +class time_point; +class tinymap; +class uilist; +struct body_part_type; +struct field_type; +struct point; +struct tripoint; + + +// These definitions help the doc generator +LUNA_DOC( bool, "bool" ); +LUNA_DOC( int, "int" ); +LUNA_DOC( size_t, "int" ); +LUNA_DOC( float, "double" ); +LUNA_DOC( double, "double" ); +LUNA_DOC( void, "nil" ); +LUNA_DOC( char, "char" ); +LUNA_DOC( const char *, "string" ); +LUNA_DOC( std::string, "string" ); +LUNA_DOC( std::string_view, "string" ); +LUNA_DOC( sol::lua_nil_t, "nil" ); +LUNA_DOC( sol::variadic_args, "..." ); +LUNA_DOC( sol::this_state, "" ); +LUNA_DOC( sol::protected_function, "function" ); + + +// These definitions are for the bindings generator +LUNA_VAL( avatar, "Avatar" ); +LUNA_VAL( Character, "Character" ); +LUNA_VAL( color_id, "Color" ); +LUNA_VAL( Creature, "Creature" ); +LUNA_VAL( distribution_grid_tracker, "DistributionGridTracker" ); +LUNA_VAL( distribution_grid, "DistributionGrid" ); +LUNA_VAL( item_stack, "ItemStack" ); +LUNA_VAL( item, "Item" ); +LUNA_VAL( map_stack, "MapStack" ); +LUNA_VAL( map, "Map" ); +LUNA_VAL( monster, "Monster" ); +LUNA_VAL( npc, "Npc" ); +LUNA_VAL( player, "Player" ); +LUNA_VAL( point, "Point" ); +LUNA_VAL( query_popup, "QueryPopup" ); +LUNA_VAL( time_duration, "TimeDuration" ); +LUNA_VAL( time_point, "TimePoint" ); +LUNA_VAL( tinymap, "Tinymap" ); +LUNA_VAL( tripoint, "Tripoint" ); +LUNA_VAL( uilist, "UiList" ); + + +// Ids for in-game objects +LUNA_ID( body_part_type, "BodyPartType" ) +LUNA_ID( effect_type, "EffectType" ) +LUNA_ID( faction, "Faction" ) +LUNA_ID( field_type, "FieldType" ) +LUNA_ID( furn_t, "Furn" ) +LUNA_ID( itype, "Itype" ) +LUNA_ID( ter_t, "Ter" ) + + +// Enums +LUNA_ENUM( game_message_type, "MsgType" ) + + +#endif // CATA_SRC_CATALUA_LUNA_DOC_H diff --git a/src/catalua_readonly.cpp b/src/catalua_readonly.cpp new file mode 100644 index 000000000000..e7ff91b43015 --- /dev/null +++ b/src/catalua_readonly.cpp @@ -0,0 +1,49 @@ +#ifdef LUA +#include "catalua_readonly.h" + +#include "catalua_sol.h" + +static int deny_table_readonly( sol::this_state L ) +{ + return luaL_error( L.lua_state(), "This table is read-only." ); +} + +// HACK that reimplements pairs() to work on the readonly table. +// TODO: check how broken this HACK is +static std::tuple +reimpl_default_pairs( sol::this_state L, sol::table t ) +{ + sol::state_view lua( L.lua_state() ); + // Forward to the table we're reading from + return std::make_tuple( lua["next"], t[sol::meta_function::index], sol::nil ); +} + +sol::table cata::make_readonly_table( sol::state_view &lua, sol::table read_from ) +{ + sol::table ret = lua.create_table(); + + read_from[sol::meta_function::index] = read_from; + read_from[sol::meta_function::new_index] = deny_table_readonly; + read_from[sol::meta_function::pairs] = reimpl_default_pairs; + + ret[sol::metatable_key] = read_from; + return ret; +} + +sol::table cata::make_readonly_table( sol::state_view &lua, sol::table read_from, + const std::string &error_msg ) +{ + sol::table ret = lua.create_table(); + + const std::string © = error_msg; + read_from[sol::meta_function::index] = read_from; + read_from[sol::meta_function::new_index] = [copy]( sol::this_state L ) { + return luaL_error( L.lua_state(), copy.c_str() ); + }; + read_from[sol::meta_function::pairs] = reimpl_default_pairs; + + ret[sol::metatable_key] = read_from; + return ret; +} + +#endif diff --git a/src/catalua_readonly.h b/src/catalua_readonly.h new file mode 100644 index 000000000000..b4c92729a61f --- /dev/null +++ b/src/catalua_readonly.h @@ -0,0 +1,16 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_READONLY_H +#define CATA_SRC_CATALUA_READONLY_H + +#include "catalua_sol_fwd.h" + +namespace cata +{ + +sol::table make_readonly_table( sol::state_view &lua, sol::table read_from ); +sol::table make_readonly_table( sol::state_view &lua, sol::table read_from, + const std::string &error_msg ); + +} // namespace cata + +#endif // CATA_SRC_CATALUA_READONLY_H diff --git a/src/catalua_serde.cpp b/src/catalua_serde.cpp new file mode 100644 index 000000000000..5ed57c950a0a --- /dev/null +++ b/src/catalua_serde.cpp @@ -0,0 +1,233 @@ +#if defined(LUA) +#include "catalua_serde.h" + +#include "catalua_sol.h" +#include "debug.h" +#include "json.h" +#include "string_formatter.h" + +#include +#include + +namespace cata +{ +// Forward declaration to make g++ happy +void serialize_lua_table_internal( sol::table t, JsonOut &jsout, std::vector &stack ); + +void serialize_lua_table_internal( sol::table t, JsonOut &jsout, std::vector &stack ) +{ + for( const sol::table &it : stack ) { + if( it == t ) { + debugmsg( "Tried to serialize recursive table structure." ); + jsout.write_null(); + return; + } + } + + stack.push_back( t ); + + sol::state_view lua( t.lua_state() ); + + jsout.start_object(); + + std::vector keys; + + t.for_each( [&]( sol::object key_obj, sol::object /*val_obj*/ ) { + std::string key = key_obj.as(); + keys.push_back( key ); + } ); + + std::sort( keys.begin(), keys.end() ); + + for( const std::string &key : keys ) { + jsout.member( key ); + sol::object val = t[key]; + + switch( val.get_type() ) { + case sol::type::boolean: { + jsout.write( val.as() ); + break; + } + case sol::type::number: { + // Horrible hack + sol::protected_function math_type = lua.script( "return math.type" ); + if( !math_type ) { + debugmsg( "Int/float serialization hack failed to acquare math.type" ); + jsout.write_null(); + } else { + sol::protected_function_result res = math_type( val ); + if( res.status() != sol::call_status::ok ) { + sol::error err = res; + debugmsg( "Int/float serialization hack failed to run math.type: %s", err.what() ); + jsout.write_null(); + } else { + sol::object retval = res; + if( !retval.valid() ) { + debugmsg( "Int/float serialization hack returned invalid value" ); + jsout.write_null(); + } else { + std::string mtype = res; + // There's no clear difference in JSON between int and float, + // so we have to be explicit to avoid subtle errors down the line + if( mtype == "integer" ) { + jsout.start_object(); + jsout.member_as_string( "type", "int" ); + jsout.member( "data" ); + jsout.write( val.as() ); + jsout.end_object(); + } else if( mtype == "float" ) { + jsout.start_object(); + jsout.member_as_string( "type", "float" ); + jsout.member( "data" ); + jsout.write( val.as() ); + jsout.end_object(); + } else { + debugmsg( "Int/float serialization hack returned invalid value: %s", mtype ); + jsout.write_null(); + } + } + } + } + break; + } + case sol::type::string: { + jsout.write( val.as() ); + break; + } + case sol::type::table: { + jsout.start_object(); + jsout.member_as_string( "type", "lua_table" ); + jsout.member( "data" ); + serialize_lua_table_internal( val.as(), jsout, stack ); + jsout.end_object(); + break; + } + case sol::type::userdata: { + sol::table table_val = val.as(); + if( !table_val.valid() ) { + debugmsg( "Sanity check failed - serializable type can be converted to table." ); + jsout.write_null(); + break; + } + try { + if( !table_val["get_luna_type"].valid() ) { + debugmsg( "Tried to serialize usertype that was not registered with luna." ); + jsout.write_null(); + break; + } + } catch( sol::error &e ) { + debugmsg( "Tried to serialize userdata that was not registered as usertype." ); + jsout.write_null(); + break; + } + sol::protected_function get_luna_type_func = table_val["get_luna_type"]; + sol::protected_function serialize_func = table_val["serialize"]; + + if( !get_luna_type_func ) { + debugmsg( "Tried to serialize usertype that has not been registered through luna." ); + jsout.write_null(); + break; + } + if( !serialize_func ) { + debugmsg( "Tried to serialize usertype that does not allow serialization." ); + jsout.write_null(); + break; + } + std::string kind = get_luna_type_func( val ); + jsout.start_object(); + jsout.member_as_string( "type", "userdata" ); + jsout.member_as_string( "kind", kind ); + jsout.member( "data" ); + sol::protected_function_result res = serialize_func( val, jsout ); + if( res.status() != sol::call_status::ok ) { + sol::error err = res; + debugmsg( "Failed to serialize type '%s': %s", kind, err.what() ); + } + jsout.end_object(); + break; + } + default: { + // TODO: throw error + debugmsg( "Unsupported type encountered when serializing Lua table." ); + jsout.write_null(); + break; + } + } + } + + jsout.end_object(); + + stack.pop_back(); +} + +void serialize_lua_table( sol::table t, JsonOut &jsout ) +{ + std::vector stack; + serialize_lua_table_internal( t, jsout, stack ); +} + +void deserialize_lua_table( sol::table t, JsonObject &obj ) +{ + sol::state_view lua( t.lua_state() ); + + for( JsonMember it : obj ) { + std::string key = it.name(); + if( it.test_bool() ) { + t[key] = it.get_bool(); + } else if( it.test_string() ) { + t[key] = it.get_string(); + } else if( it.test_object() ) { + JsonObject jo = it.get_object(); + std::string entry_type = jo.get_member( "type" ); + if( entry_type == "int" ) { + int data = jo.get_int( "data" ); + t[key] = data; + } else if( entry_type == "float" ) { + double data = jo.get_float( "data" ); + t[key] = data; + } else if( entry_type == "lua_table" ) { + JsonObject data = jo.get_object( "data" ); + sol::table new_table = lua.create_table(); + deserialize_lua_table( new_table, data ); + t[key] = new_table; + } else if( entry_type == "userdata" ) { + std::string kind = jo.get_member( "kind" ); + JsonIn &data_raw = *jo.get_raw( "data" ); + // Horrible hack ahead + std::string script = string_format( "return %s.new()", kind ); + sol::protected_function_result res = lua.script( script, "deserialize_init", sol::load_mode::any ); + if( res.status() != sol::call_status::ok ) { + debugmsg( "Failed to init container for deserializable type '%s'", kind ); + } else { + sol::object obj = res; + sol::table obj_table = obj.as(); + if( !obj_table ) { + debugmsg( "Failed to init container for deserializable type '%s'", kind ); + } else { + sol::protected_function deserialize_func = obj_table["deserialize"]; + if( !deserialize_func ) { + debugmsg( "Failed to deserialize type '%s': not deserializable.", kind ); + } else { + sol::protected_function_result res = deserialize_func( obj, data_raw ); + if( res.status() != sol::call_status::ok ) { + sol::error err = res; + debugmsg( "Failed to deserialize type '%s': %s", kind, err.what() ); + } else { + t[key] = obj; + } + } + } + } + } else { + debugmsg( "Deserialization of record type '%s' is not implemented.", entry_type ); + } + } else if( it.test_array() ) { + debugmsg( "Arrays are not supported when deserializing Lua table." ); + } + } +} + +} // namespace cata + +#endif + diff --git a/src/catalua_serde.h b/src/catalua_serde.h new file mode 100644 index 000000000000..a8a48e60a1c1 --- /dev/null +++ b/src/catalua_serde.h @@ -0,0 +1,18 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_SERDE_H +#define CATA_SRC_CATALUA_SERDE_H + +#include "catalua_sol_fwd.h" + +class JsonObject; +class JsonOut; + +namespace cata +{ + +void serialize_lua_table( sol::table t, JsonOut &jsout ); +void deserialize_lua_table( sol::table t, JsonObject &obj ); + +} // namespace cata + +#endif // CATA_SRC_CATALUA_SERDE_H diff --git a/src/catalua_sol.h b/src/catalua_sol.h new file mode 100644 index 000000000000..08e52152505b --- /dev/null +++ b/src/catalua_sol.h @@ -0,0 +1,22 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_SOL_H +#define CATA_SRC_CATALUA_SOL_H + +#ifdef __clang__ +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wold-style-cast" +# pragma clang diagnostic ignored "-Wmissing-noreturn" +# pragma clang diagnostic ignored "-Wzero-as-null-pointer-constant" +#endif + +#define CATALUA_SOL_WRAPPED + +#include "sol/sol.hpp" + +#undef CATALUA_SOL_WRAPPED + +#ifdef __clang__ +# pragma clang diagnostic pop +#endif + +#endif // CATA_SRC_CATALUA_SOL_H diff --git a/src/catalua_sol_fwd.h b/src/catalua_sol_fwd.h new file mode 100644 index 000000000000..913a18e92cec --- /dev/null +++ b/src/catalua_sol_fwd.h @@ -0,0 +1,7 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_SOL_FWD_H +#define CATA_SRC_CATALUA_SOL_FWD_H + +#include "sol/forward.hpp" + +#endif // CATA_SRC_CATALUA_SOL_FWD_H diff --git a/src/catalua_type_operators.h b/src/catalua_type_operators.h new file mode 100644 index 000000000000..11aba63712b3 --- /dev/null +++ b/src/catalua_type_operators.h @@ -0,0 +1,33 @@ +#pragma once +#ifndef CATA_SRC_CATALUA_TYPE_OPERATORS_H +#define CATA_SRC_CATALUA_TYPE_OPERATORS_H + +/** + * Due to some strange behavior in sol2, we need to define + * comparison operators for types that are referenced by string_id or int_id. + * For details, see https://github.com/ThePhD/sol2/issues/1264 + * string_id and int_id essentially act like smart pointers + * and implement comparison operators, meaning T also has to implement them. + * + * You can use this macro as a quick solution, just pass the type as T + * and the member/method that contains/returns the id as id_getter. + * + * Example implementation: + * ```c++ + * class ter_t { + * ter_str_id id; + * ... + * LUA_TYPE_OPS( ter_t, id ); + * ... + * } + * ``` + */ +#define LUA_TYPE_OPS( T, id_getter ) \ + inline bool operator==( const T &rhs ) const { \ + return id_getter == rhs.id_getter; \ + }; \ + inline bool operator<( const T &rhs ) const { \ + return id_getter < rhs.id_getter; \ + } + +#endif // CATA_SRC_CATALUA_TYPE_OPERATORS_H diff --git a/src/character.cpp b/src/character.cpp index 94fe90929300..6965a7d01277 100644 --- a/src/character.cpp +++ b/src/character.cpp @@ -3729,15 +3729,13 @@ bool Character::worn_with_flag( const std::string &flag, const bodypart_id &bp ) const item *Character::item_worn_with_flag( const std::string &flag, const bodypart_id &bp ) const { - const item *it_with_flag = nullptr; for( const item * const &it : worn ) { if( it->has_flag( flag ) && ( bp == bodypart_str_id::NULL_ID() || it->covers( bp->token ) ) ) { - it_with_flag = it; - break; + return it; } } - return it_with_flag; + return nullptr; } std::vector Character::get_overlay_ids() const @@ -3750,7 +3748,7 @@ std::vector Character::get_overlay_ids() const // first get effects for( const auto &eff_pr : *effects ) { if( !eff_pr.second.begin()->second.is_removed() ) { - rval.push_back( "effect_" + eff_pr.first.str() ); + rval.emplace_back( "effect_" + eff_pr.first.str() ); } } diff --git a/src/character.h b/src/character.h index 819a9abf2dff..fdee0ebefecd 100644 --- a/src/character.h +++ b/src/character.h @@ -2080,7 +2080,7 @@ class Character : public Creature, public location_visitable bool change_side( item &it, bool interactive = true ); bool change_side( item *it, bool interactive = true ); - bool get_check_encumbrance() { + bool get_check_encumbrance() const { return check_encumbrance; } void set_check_encumbrance( bool new_check ) { diff --git a/src/color.h b/src/color.h index e27b6224af2a..a57ed61464df 100644 --- a/src/color.h +++ b/src/color.h @@ -169,7 +169,7 @@ class translation; #define c_light_cyan_cyan all_colors.get(def_c_light_cyan_cyan) // def_x is a color that maps to x with default settings -enum color_id { +enum color_id : int { def_c_black = 0, def_c_white, def_c_light_gray, diff --git a/src/crash.cpp b/src/crash.cpp index f302e810c189..479f01525aa4 100644 --- a/src/crash.cpp +++ b/src/crash.cpp @@ -55,6 +55,13 @@ extern "C" { #endif const std::string crash_log_file = PATH_INFO::crash(); std::ostringstream log_text; +#if defined(__ANDROID__) + // At this point, Android JVM is already doomed + // No further UI interaction (including the SDL message box) + // Show a dialogue at next launch + log_text << "VERSION: " << getVersionString() + << '\n' << type << ' ' << msg; +#else log_text << "The program has crashed." << "\nSee the log file for a stack trace." << "\nCRASH LOG FILE: " << crash_log_file @@ -66,6 +73,7 @@ extern "C" { log_text.str().c_str(), nullptr ) != 0 ) { log_text << "Error creating SDL message box: " << SDL_GetError() << '\n'; } +#endif #endif log_text << "\nSTACK TRACE:\n"; debug_write_backtrace( log_text ); @@ -75,6 +83,15 @@ extern "C" { fwrite( log_text.str().data(), 1, log_text.str().size(), file ); fclose( file ); } +#if defined(__ANDROID__) + // Create a placeholder dummy file "config/crash.log.prompt" + // to let the app show a dialog box at next start + file = fopen( ( crash_log_file + ".prompt" ).c_str(), "w" ); + if( file ) { + fwrite( "0", 1, 1, file ); + fclose( file ); + } +#endif } static void signal_handler( int sig ) diff --git a/src/creature.cpp b/src/creature.cpp index 7cbfb5cf0157..7942b2d58250 100644 --- a/src/creature.cpp +++ b/src/creature.cpp @@ -1730,6 +1730,7 @@ bodypart_id Creature::get_random_body_part( bool main ) const std::vector Creature::get_all_body_parts( bool only_main ) const { std::vector all_bps; + all_bps.reserve( body.size() ); for( const std::pair &elem : body ) { if( only_main && elem.first->main_part != elem.first ) { continue; diff --git a/src/debug.cpp b/src/debug.cpp index 8225881f366e..ba05c6e78ef2 100644 --- a/src/debug.cpp +++ b/src/debug.cpp @@ -18,6 +18,7 @@ #include #include #include +#include #include #include #include @@ -25,6 +26,7 @@ #include #include +#include "catalua.h" #include "cata_utility.h" #include "cached_options.h" #include "color.h" @@ -40,7 +42,6 @@ #include "output.h" #include "path_info.h" #include "point.h" -#include "sdl_wrappers.h" #include "string_utils.h" #include "translations.h" #include "type_id.h" @@ -61,19 +62,34 @@ # if defined(_WIN32) # include # if defined(LIBBACKTRACE) -# include +# include # endif +# elif defined(__ANDROID__) +# include +# include # else # include # include # endif #endif +#if defined(LIBBACKTRACE) +# include +#endif + +#if defined(TILES) +#include "sdl_wrappers.h" +#endif // TILES + #if defined(__ANDROID__) // used by android_version() function for __system_property_get(). #include #endif +#if (defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__)) && !defined(BSD) +#define BSD +#endif + // Hack for loading weird saves bool dont_debugmsg = false; @@ -97,6 +113,64 @@ static bool capturing = false; /** сaptured debug messages */ static std::string captured; + +#if defined(_WIN32) and defined(LIBBACKTRACE) +// Get the image base of a module from its PE header +static uintptr_t get_image_base( const char *const path ) +{ + HANDLE file = CreateFile( path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, + FILE_ATTRIBUTE_NORMAL, NULL ); + if( file == INVALID_HANDLE_VALUE ) { + return 0; + } + on_out_of_scope close_file( [file]() { + CloseHandle( file ); + } ); + + HANDLE mapping = CreateFileMapping( file, NULL, PAGE_READONLY, 0, 0, NULL ); + if( mapping == NULL ) { + return 0; + } + on_out_of_scope close_mapping( [mapping]() { + CloseHandle( mapping ); + } ); + + LONG nt_header_offset = 0; + { + LPVOID dos_header_view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, sizeof( IMAGE_DOS_HEADER ) ); + if( dos_header_view == NULL ) { + return 0; + } + on_out_of_scope close_dos_header_view( [dos_header_view]() { + UnmapViewOfFile( dos_header_view ); + } ); + + PIMAGE_DOS_HEADER dos_header = reinterpret_cast( dos_header_view ); + if( dos_header->e_magic != IMAGE_DOS_SIGNATURE ) { + return 0; + } + nt_header_offset = dos_header->e_lfanew; + } + + LPVOID pe_header_view = MapViewOfFile( mapping, FILE_MAP_READ, 0, 0, + nt_header_offset + sizeof( IMAGE_NT_HEADERS ) ); + if( pe_header_view == NULL ) { + return 0; + } + on_out_of_scope close_pe_header_view( [pe_header_view]() { + UnmapViewOfFile( pe_header_view ); + } ); + + PIMAGE_NT_HEADERS nt_header = reinterpret_cast( + reinterpret_cast( pe_header_view ) + nt_header_offset ); + if( nt_header->Signature != IMAGE_NT_SIGNATURE + || nt_header->FileHeader.SizeOfOptionalHeader != sizeof( IMAGE_OPTIONAL_HEADER ) ) { + return 0; + } + return nt_header->OptionalHeader.ImageBase; +} +#endif + /** * Class for capturing debugmsg, * used by capture_debugmsg_during. @@ -498,11 +572,12 @@ void debug_reset_ignored_messages() // Null OStream {{{2 // --------------------------------------------------------------------- -struct NullBuf : public std::streambuf { - NullBuf() = default; - int overflow( int c ) override { - return c; - } +class NullStream : public std::ostream +{ + public: + NullStream() : std::ostream( nullptr ) {} + NullStream( const NullStream & ) = delete; + NullStream( NullStream && ) = delete; }; // DebugFile OStream Wrapper {{{2 @@ -679,6 +754,7 @@ std::string enum_to_string( DC x ) case DC::MapMem: return "MAPMEM"; case DC::NPC: return "NPC"; case DC::SDL: return "SDL"; + case DC::Lua: return "LUA"; // *INDENT-ON* case DC::Num: break; @@ -689,7 +765,7 @@ std::string enum_to_string( DC x ) } // namespace io #if defined(BACKTRACE) -#if !defined(_WIN32) && !defined(__CYGWIN__) +#if !defined(_WIN32) && !defined(__CYGWIN__) && !defined(__ANDROID__) && !defined(LIBBACKTRACE) // Verify that a string is safe for passing as an argument to addr2line. // In particular, we want to avoid any characters of significance to the shell. static bool debug_is_safe_string( const char *start, const char *finish ) @@ -795,7 +871,7 @@ static std::optional debug_compute_load_offset( } #endif -#if defined(_WIN32) && defined(LIBBACKTRACE) +#if defined(LIBBACKTRACE) // wrap libbacktrace to use std::function instead of function pointers using bt_error_callback = std::function; using bt_full_callback = std::function; @@ -812,6 +888,28 @@ static backtrace_state *bt_create_state( const char *const filename, const int t const_cast( &cb ) ); } + +#if !defined(_WIN32) +static int bt_full( backtrace_state *const state, int skip, const bt_full_callback &cb_full, + const bt_error_callback &cb_error ) +{ + using cb_pair = std::pair; + cb_pair cb { cb_full, cb_error }; + return backtrace_full( state, skip, + // backtrace callback + []( void *const data, const uintptr_t pc, const char *const filename, + const int lineno, const char *const function ) -> int { + cb_pair &cb = *reinterpret_cast( data ); + return cb.first( pc, filename, lineno, function ); + }, + // error callback + []( void *const data, const char *const msg, const int errnum ) { + cb_pair &cb = *reinterpret_cast( data ); + cb.second( msg, errnum ); + }, + &cb ); +} +#else static int bt_pcinfo( backtrace_state *const state, const uintptr_t pc, const bt_full_callback &cb_full, const bt_error_callback &cb_error ) { @@ -852,6 +950,7 @@ static int bt_syminfo( backtrace_state *const state, const uintptr_t addr, &cb ); } #endif +#endif #if defined(_WIN32) class sym_init @@ -880,15 +979,88 @@ static struct { } sym_storage; static SYMBOL_INFO &sym = reinterpret_cast( sym_storage ); #if defined(LIBBACKTRACE) -static std::map bt_states; +struct backtrace_module_info_t { + backtrace_state *state = nullptr; + uintptr_t image_base = 0; +}; +static std::map bt_module_info_map; #endif -#else +#elif !defined(__ANDROID__) && !defined(LIBBACKTRACE) constexpr int bt_cnt = 20; static void *bt[bt_cnt]; #endif +#if !defined(_WIN32) && !defined(__ANDROID__) && !defined(LIBBACKTRACE) +static void write_demangled_frame( std::ostream &out, const char *frame ) +{ +#if defined(__linux__) + // ./cataclysm(_ZN4game13handle_actionEv+0x47e8) [0xaaaae91e80fc] + static const std::regex symbol_regex( R"(^(.*)\((.*)\+(0x?[a-f0-9]*)\)\s\[(0x[a-f0-9]+)\]$)" ); + std::cmatch match_result; + if( std::regex_search( frame, match_result, symbol_regex ) && match_result.size() == 5 ) { + std::csub_match file_name = match_result[1]; + std::csub_match raw_symbol_name = match_result[2]; + std::csub_match offset = match_result[3]; + std::csub_match address = match_result[4]; + out << "\n " << file_name.str() << "(" << demangle( raw_symbol_name.str().c_str() ) << "+" << + offset.str() << ") [" << address.str() << "]"; + } else { + out << "\n " << frame; + } +#elif defined(MACOSX) + //1 cataclysm-tiles 0x0000000102ba2244 _ZL9log_crashPKcS0_ + 608 + static const std::regex symbol_regex( R"(^(.*)(0x[a-f0-9]{16})\s(.*)\s\+\s([0-9]+)$)" ); + std::cmatch match_result; + if( std::regex_search( frame, match_result, symbol_regex ) && match_result.size() == 5 ) { + std::csub_match prefix = match_result[1]; + std::csub_match address = match_result[2]; + std::csub_match raw_symbol_name = match_result[3]; + std::csub_match offset = match_result[4]; + out << "\n " << prefix.str() << address.str() << ' ' << demangle( raw_symbol_name.str().c_str() ) + << " + " << offset.str(); + } else { + out << "\n " << frame; + } +#elif defined(BSD) + static const std::regex symbol_regex( R"(^(0x[a-f0-9]+)\s<(.*)\+(0?x?[a-f0-9]*)>\sat\s(.*)$)" ); + std::cmatch match_result; + if( std::regex_search( frame, match_result, symbol_regex ) && match_result.size() == 5 ) { + std::csub_match address = match_result[1]; + std::csub_match raw_symbol_name = match_result[2]; + std::csub_match offset = match_result[3]; + std::csub_match file_name = match_result[4]; + out << "\n " << address.str() << " <" << demangle( raw_symbol_name.str().c_str() ) << "+" << + offset.str() << "> at " << file_name.str(); + } else { + out << "\n " << frame; + } +#else + out << "\n " << frame; +#endif +} +#endif // !defined(_WIN32) && !defined(__ANDROID__) + + +#if !defined(__ANDROID__) void debug_write_backtrace( std::ostream &out ) { +#if defined(LIBBACKTRACE) + auto bt_full_print = [&out]( const uintptr_t pc, const char *const filename, + const int lineno, const char *const function ) -> int { + std::string file = filename ? filename : "[unknown src]"; + size_t src = file.find( "/src/" ); + if( src != std::string::npos ) + { + file.erase( 0, src ); + file = "…" + file; + } + out << "\n 0x" << std::hex << pc << std::dec + << " " << file << ":" << lineno + << " " << ( function ? demangle( function ) : "[unknown func]" ); + return 0; + }; +#endif + #if defined(_WIN32) if( !sym_init_ ) { sym_init_ = std::make_unique(); @@ -903,7 +1075,7 @@ void debug_write_backtrace( std::ostream &out ) out << "\n #" << i; out << "\n (dbghelp: "; if( SymFromAddr( proc, reinterpret_cast( bt[i] ), &off, &sym ) ) { - out << sym.Name << "+0x" << std::hex << off << std::dec; + out << demangle( sym.Name ) << "+0x" << std::hex << off << std::dec; } out << "@" << bt[i]; const DWORD64 mod_base = SymGetModuleBase64( proc, reinterpret_cast( bt[i] ) ); @@ -925,39 +1097,37 @@ void debug_write_backtrace( std::ostream &out ) } out << "), "; #if defined(LIBBACKTRACE) - backtrace_state *bt_state = nullptr; + backtrace_module_info_t bt_module_info; if( mod_base ) { - const auto it = bt_states.find( mod_base ); - if( it != bt_states.end() ) { - bt_state = it->second; + const auto it = bt_module_info_map.find( mod_base ); + if( it != bt_module_info_map.end() ) { + bt_module_info = it->second; } else { const DWORD mod_len = GetModuleFileName( reinterpret_cast( mod_base ), mod_path, module_path_len ); if( mod_len > 0 && mod_len < module_path_len ) { - bt_state = bt_create_state( mod_path, 0, - // error callback + bt_module_info.state = bt_create_state( mod_path, 0, + // error callback [&out]( const char *const msg, const int errnum ) { out << "\n (backtrace_create_state failed: errno = " << errnum << ", msg = " << ( msg ? msg : "[no msg]" ) << "),"; } ); + bt_module_info.image_base = get_image_base( mod_path ); + if( bt_module_info.image_base == 0 ) { + out << "\n (cannot locate image base),"; + } } else { out << "\n (executable path exceeds " << module_path_len << " chars),"; } - if( bt_state ) { - bt_states.emplace( mod_base, bt_state ); - } + bt_module_info_map.emplace( mod_base, bt_module_info ); } } else { out << "\n (unable to get module base address),"; } - if( bt_state ) { -#if defined(__MINGW64__) - constexpr uint64_t static_image_base = 0x140000000ULL; -#elif defined(__MINGW32__) - constexpr uint64_t static_image_base = 0x400000ULL; -#endif - uint64_t de_aslr_pc = reinterpret_cast( bt[i] ) - mod_base + static_image_base; - bt_syminfo( bt_state, de_aslr_pc, + if( bt_module_info.state && bt_module_info.image_base != 0 ) { + const uintptr_t de_aslr_pc = reinterpret_cast( bt[i] ) - mod_base + + bt_module_info.image_base; + bt_syminfo( bt_module_info.state, de_aslr_pc, // syminfo callback [&out]( const uintptr_t pc, const char *const symname, const uintptr_t symval, const uintptr_t ) { @@ -972,18 +1142,8 @@ void debug_write_backtrace( std::ostream &out ) << ", msg = " << ( msg ? msg : "[no msg]" ) << "),"; } ); - bt_pcinfo( bt_state, de_aslr_pc, - // backtrace callback - [&out]( const uintptr_t pc, const char *const filename, - const int lineno, const char *const function ) -> int { - out << "\n (libbacktrace: 0x" << std::hex << pc << std::dec - << " " << ( filename ? filename : "[unknown src]" ) - << ":" << lineno - << " " << ( function ? function : "[unknown func]" ) - << "),"; - return 0; - }, - // error callback + bt_pcinfo( bt_module_info.state, de_aslr_pc, bt_full_print, + // error callback [&out]( const char *const msg, const int errnum ) { out << "\n (backtrace_pcinfo failed: errno = " << errnum << ", msg = " << ( msg ? msg : "[no msg]" ) @@ -994,14 +1154,25 @@ void debug_write_backtrace( std::ostream &out ) } out << "\n"; #else -# if defined(__CYGWIN__) +# if defined(LIBBACKTRACE) + auto bt_error = [&out]( const char *err_msg, int errnum ) { + out << "\n libbacktrace error " << errnum << ": " << err_msg; + }; + static backtrace_state *bt_state = bt_create_state( nullptr, 0, bt_error ); + if( bt_state ) { + bt_full( bt_state, 0, bt_full_print, bt_error ); + out << std::endl; + } else { + out << "\n\n Failed to initialize libbacktrace\n"; + } +# elif defined(__CYGWIN__) // BACKTRACE is not supported under CYGWIN! ( void ) out; # else int count = backtrace( bt, bt_cnt ); char **funcNames = backtrace_symbols( bt, count ); for( int i = 0; i < count; ++i ) { - out << "\n " << funcNames[i]; + write_demangled_frame( out, funcNames[i] ); } out << "\n\n Attempting to repeat stack trace using debug symbols…\n"; // Try to print the backtrace again, but this time using addr2line @@ -1131,6 +1302,51 @@ void debug_write_backtrace( std::ostream &out ) #endif } #endif +#endif + +// Probably because there are too many nested #if..#else..#endif in this file +// NDK compiler doesn't understand #if defined(__ANDROID__)..#else..#endif +// So write as two separate #if blocks +#if defined(__ANDROID__) + +// The following Android backtrace code was originally written by Eugene Shapovalov +// on https://stackoverflow.com/questions/8115192/android-ndk-getting-the-backtrace +struct android_backtrace_state { + void **current; + void **end; +}; + +static _Unwind_Reason_Code unwindCallback( struct _Unwind_Context *context, void *arg ) +{ + android_backtrace_state *state = static_cast( arg ); + uintptr_t pc = _Unwind_GetIP( context ); + if( pc ) { + if( state->current == state->end ) { + return _URC_END_OF_STACK; + } else { + *state->current++ = reinterpret_cast( pc ); + } + } + return _URC_NO_REASON; +} + +void debug_write_backtrace( std::ostream &out ) +{ + const size_t max = 50; + void *buffer[max]; + android_backtrace_state state = {buffer, buffer + max}; + _Unwind_Backtrace( unwindCallback, &state ); + const std::size_t count = state.current - buffer; + // Start from 1: skip debug_write_backtrace ourselves + for( size_t idx = 1; idx < count && idx < max; ++idx ) { + const void *addr = buffer[idx]; + Dl_info info; + if( dladdr( addr, &info ) && info.dli_sname ) { + out << "#" << std::setw( 2 ) << idx << ": " << addr << " " << demangle( info.dli_sname ) << "\n"; + } + } +} +#endif void output_repetitions( std::ostream &out ) { @@ -1201,6 +1417,7 @@ detail::DebugLogGuard detail::realDebugLog( DL lev, DC cl, const char *filename, // Cool down for 60s between backtrace emissions. next_backtrace = after + 60; out << "Backtrace emission took " << after - now << " seconds." << std::endl; + cata::debug_write_lua_backtrace( out ); out << "(continued from above) " << io::enum_to_string( lev ) << ": "; } #endif @@ -1208,9 +1425,8 @@ detail::DebugLogGuard detail::realDebugLog( DL lev, DC cl, const char *filename, return DebugLogGuard( out ); } - static NullBuf nullBuf; - static std::ostream nullStream( &nullBuf ); - return DebugLogGuard( nullStream ); + static NullStream null_stream; + return DebugLogGuard( null_stream ); } std::string game_info::operating_system() @@ -1237,7 +1453,7 @@ std::string game_info::operating_system() /* OSX */ return "MacOs"; #endif // TARGET_IPHONE_SIMULATOR -#elif defined(BSD) // defined(__DragonFly__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) +#elif defined(BSD) return "BSD"; #else return "Unix"; @@ -1421,13 +1637,44 @@ static std::string windows_version() output.append( std::to_string( minor_version ) ); } } - if( success && major_version == 10 ) { + if( success ) { buffer_size = c_buffer_size; - success = RegQueryValueExA( handle_key, "ReleaseId", nullptr, &value_type, &byte_buffer[0], + success = RegQueryValueExA( handle_key, "CurrentBuildNumber", nullptr, &value_type, &byte_buffer[0], &buffer_size ) == ERROR_SUCCESS && value_type == REG_SZ; + + if( success ) { + output.append( "." ); + output.append( std::string( reinterpret_cast( &byte_buffer[0] ) ) ); + } if( success ) { - output.append( " " ); - output.append( std::string( reinterpret_cast( byte_buffer.data() ) ) ); + buffer_size = c_buffer_size; + success = RegQueryValueExA( handle_key, "UBR", nullptr, &value_type, &byte_buffer[0], + &buffer_size ) == ERROR_SUCCESS && value_type == REG_DWORD; + if( success ) { + output.append( "." ); + output.append( std::to_string( *reinterpret_cast( &byte_buffer[0] ) ) ); + } + } + + // Applies to both Windows 10 and Windows 11 + if( major_version == 10 ) { + buffer_size = c_buffer_size; + // present in Windows 10 version >= 20H2 (aka 2009) and Windows 11 + success = RegQueryValueExA( handle_key, "DisplayVersion", nullptr, &value_type, &byte_buffer[0], + &buffer_size ) == ERROR_SUCCESS && value_type == REG_SZ; + + if( !success ) { + // only accurate in Windows 10 version <= 2009 + buffer_size = c_buffer_size; + success = RegQueryValueExA( handle_key, "ReleaseId", nullptr, &value_type, &byte_buffer[0], + &buffer_size ) == ERROR_SUCCESS && value_type == REG_SZ; + } + + if( success ) { + output.append( " (" ); + output.append( std::string( reinterpret_cast( byte_buffer.data() ) ) ); + output.append( ")" ); + } } } @@ -1547,11 +1794,14 @@ std::string game_info::game_report() } } + // Note: We shorten 'Lua API' to 'LAPI' so that 'Lua' word does not show up + // in every issue out there and pollute GitHub issue search results. report << "- OS: " << operating_system() << "\n" << " - OS Version: " << os_version << "\n" << "- Game Version: " << game_version() << " [" << bitness() << "]\n" << "- Graphics Version: " << graphics_version() << "\n" << + "- LAPI Version: " << cata::get_lapi_version_string() << "\n" << "- Game Language: " << lang_translated << " [" << lang << "]\n" << "- Mods loaded: [\n " << mods_loaded() << "\n]\n"; diff --git a/src/debug.h b/src/debug.h index 87f764e16f3a..0c5ee2080b34 100644 --- a/src/debug.h +++ b/src/debug.h @@ -184,6 +184,8 @@ enum class DC : int { NPC, /** SDL & tiles & anything graphical & sound */ SDL, + /** Output from Lua */ + Lua, /** Unused */ Num, }; diff --git a/src/debug_menu.cpp b/src/debug_menu.cpp index 779bcd6f8b71..df9944d406e0 100644 --- a/src/debug_menu.cpp +++ b/src/debug_menu.cpp @@ -30,6 +30,7 @@ #include "calendar.h" #include "cata_utility.h" #include "catacharset.h" +#include "catalua.h" #include "character.h" #include "character_display.h" #include "character_id.h" @@ -51,6 +52,8 @@ #include "inventory.h" #include "item.h" #include "item_group.h" +#include "json.h" +#include "json_export.h" #include "language.h" #include "magic.h" #include "map.h" @@ -162,6 +165,7 @@ enum debug_menu_index { DEBUG_PRINT_FACTION_INFO, DEBUG_PRINT_NPC_MAGIC, DEBUG_QUIT_NOSAVE, + DEBUG_LUA_CONSOLE, DEBUG_TEST_WEATHER, DEBUG_SAVE_SCREENSHOT, DEBUG_BUG_REPORT, @@ -177,6 +181,7 @@ enum debug_menu_index { DEBUG_DISPLAY_SUBMAP_GRID, DEBUG_TEST_MAP_EXTRA_DISTRIBUTION, DEBUG_VEHICLE_BATTERY_CHARGE, + DEBUG_VEHICLE_EXPORT_JSON, DEBUG_HOUR_TIMER, DEBUG_NESTED_MAPGEN, DEBUG_RESET_IGNORED_MESSAGES, @@ -253,6 +258,7 @@ static int vehicle_uilist() { std::vector uilist_initializer = { { uilist_entry( DEBUG_VEHICLE_BATTERY_CHARGE, true, 'b', _( "Change [b]attery charge" ) ) }, + { uilist_entry( DEBUG_VEHICLE_EXPORT_JSON, true, 'j', _( "Export [j]son template" ) ) }, }; return uilist( _( "Vehicle…" ), uilist_initializer ); @@ -329,6 +335,10 @@ static int debug_menu_uilist( bool display_all_entries = true ) // insert debug-only menu right after "Info". menu.insert( menu.begin() + 1, debug_menu.begin(), debug_menu.end() ); + + if( cata::has_lua() ) { + menu.push_back( uilist_entry( 7, true, 'l', _( "Lua console" ) ) ); + } } std::string msg; @@ -366,7 +376,9 @@ static int debug_menu_uilist( bool display_all_entries = true ) case 6: action = vehicle_uilist(); break; - + case 7: + action = DEBUG_LUA_CONSOLE; + break; default: return group; } @@ -2004,6 +2016,10 @@ void debug() g->uquit = QUIT_NOSAVED; } break; + case DEBUG_LUA_CONSOLE: { + cata::show_lua_console(); + break; + } case DEBUG_TEST_WEATHER: { get_weather().get_cur_weather_gen().test_weather( g->get_seed() ); } @@ -2069,6 +2085,31 @@ void debug() } break; } + case DEBUG_VEHICLE_EXPORT_JSON: { + const optional_vpart_position v_part_pos = g->m.veh_at( u.pos() ); + if( !v_part_pos ) { + add_msg( m_bad, _( "There's no vehicle there." ) ); + break; + } + const vehicle &veh = v_part_pos->vehicle(); + std::stringstream ss; + JsonOut json( ss, true ); + json_export::vehicle( json, veh ); + + // write to log + DebugLog( DL::Info, DC::Main ) << " JSON TEMPLATE EXPORT:\n" << ss.str(); + std::string popup_msg = _( "JSON template written to debug.log" ); +#if defined(TILES) + // copy to clipboard + const int clipboard_result = SDL_SetClipboardText( ss.str().c_str() ); + printErrorIf( clipboard_result != 0, "Error while exporting JSON to the clipboard." ); + if( clipboard_result == 0 ) { + popup_msg += _( " and to the clipboard." ); + } +#endif + popup( popup_msg ); + break; + } case DEBUG_TEST_MAP_EXTRA_DISTRIBUTION: MapExtras::debug_spawn_test(); diff --git a/src/demangle.cpp b/src/demangle.cpp new file mode 100644 index 000000000000..cb63e40a5e2d --- /dev/null +++ b/src/demangle.cpp @@ -0,0 +1,34 @@ +#if defined(__GNUC__) || defined(__clang__) +# include +#endif + +#include "demangle.h" + +auto demangle( const char *symbol ) -> std::string +{ +#if defined(_MSC_VER) + // TODO: implement demangling on MSVC +#elif defined(__GNUC__) || defined(__clang__) + int status = -1; + char *demangled = abi::__cxa_demangle( symbol, nullptr, nullptr, &status ); + if( status == 0 ) { + std::string demangled_str( demangled ); + free( demangled ); + return demangled_str; + } +#if defined(_WIN32) + // https://stackoverflow.com/questions/54333608/boost-stacktrace-not-demangling-names-when-cross-compiled + // libbacktrace may strip leading underscore character in the symbol name returned + // so if demangling failed, try again with an underscore prepended + std::string prepend_underscore( "_" ); + prepend_underscore = prepend_underscore + symbol; + demangled = abi::__cxa_demangle( prepend_underscore.c_str(), nullptr, nullptr, &status ); + if( status == 0 ) { + std::string demangled_str( demangled ); + free( demangled ); + return demangled_str; + } +#endif // defined(_WIN32) +#endif // compiler macros + return std::string( symbol ); +} diff --git a/src/demangle.h b/src/demangle.h new file mode 100644 index 000000000000..c0dbb9bbd907 --- /dev/null +++ b/src/demangle.h @@ -0,0 +1,12 @@ +#pragma once +#ifndef CATA_SRC_DEMANGLE_H +#define CATA_SRC_DEMANGLE_H + +#include + +/** + * Demangles a C++ symbol + */ +auto demangle( const char *symbol ) -> std::string; + +#endif // CATA_SRC_DEMANGLE_H diff --git a/src/editmap.cpp b/src/editmap.cpp index a67fc594b9cc..70c14ebb53e2 100644 --- a/src/editmap.cpp +++ b/src/editmap.cpp @@ -1072,7 +1072,7 @@ template void editmap::edit_feature() { if( T_t::count() == 0 ) { - debugmsg( "Empty %s list", typeid( T_t ).name() ); + debugmsg( "Empty %s list", demangle( typeid( T_t ).name() ) ); return; } diff --git a/src/effect.h b/src/effect.h index c746684eeba1..1ab42c39a2de 100644 --- a/src/effect.h +++ b/src/effect.h @@ -11,6 +11,7 @@ #include "bodypart.h" #include "calendar.h" +#include "catalua_type_operators.h" #include "hash_utils.h" #include "translations.h" #include "type_id.h" @@ -94,6 +95,8 @@ class effect_type static void check_consistency(); + LUA_TYPE_OPS( effect_type, id ); + private: bool permanent = false; diff --git a/src/enum_conversions.h b/src/enum_conversions.h index 774225c4300d..7e94a6d8c865 100644 --- a/src/enum_conversions.h +++ b/src/enum_conversions.h @@ -68,7 +68,7 @@ inline E string_to_enum_look_up( const C &container, const std::string &data ) const auto iter = container.find( data ); if( iter == container.end() ) { throw InvalidEnumString( "Invalid enum string '" + data + "' for '" + - typeid( E ).name() + "'" ); + demangle( typeid( E ).name() ) + "'" ); } return iter->second; } diff --git a/src/explosion.cpp b/src/explosion.cpp index 2031001dde5b..57b6b53486a4 100644 --- a/src/explosion.cpp +++ b/src/explosion.cpp @@ -231,7 +231,7 @@ constexpr float FLING_MAX_RANGE = 50.0; // different time scale and this constant is the scaling factor // between the two constexpr float FLING_SLOWDOWN = 5.0; -}; // namespace ExplosionConstants +} // namespace ExplosionConstants namespace explosion_handler { @@ -465,7 +465,7 @@ void ExplosionProcess::fill_maps() std::stable_sort( blast_map.begin(), blast_map.end(), dist_comparator ); std::stable_sort( shrapnel_map.begin(), shrapnel_map.end(), dist_comparator ); -}; +} void ExplosionProcess::init_event_queue() { // Start with shrapnel first @@ -489,7 +489,7 @@ void ExplosionProcess::init_event_queue() // which, as stated before, converts trig_dist into int implicitly add_event( time_taken, ExplosionEvent::tile_blast( position, static_cast( distance ) ) ); } -}; +} inline bool ExplosionProcess::is_occluded( const tripoint from, const tripoint to ) { if( from == to ) { @@ -517,7 +517,7 @@ inline bool ExplosionProcess::is_occluded( const tripoint from, const tripoint t last_position = position; } return false; -}; +} inline float ExplosionProcess::generate_fling_angle( const tripoint from, const tripoint to ) { @@ -882,7 +882,7 @@ void ExplosionProcess::blast_tile( const tripoint position, const int rl_distanc } } request_redraw |= position.z == g->u.posz(); -}; +} void ExplosionProcess::add_field( const tripoint position, const field_type_id field, @@ -892,14 +892,14 @@ void ExplosionProcess::add_field( const tripoint position, map &here = get_map(); here.add_field( position, field, intensity, 0_turns, hit_player ); request_redraw |= position.z == g->u.posz(); -}; +} void ExplosionProcess::remove_field( const tripoint position, field_type_id target ) { map &here = get_map(); here.remove_field( position, target ); request_redraw |= position.z == g->u.posz(); -}; +} void ExplosionProcess::move_entity( const tripoint position, const ExplosionEvent::PropelledEntity &datum, @@ -987,7 +987,7 @@ void ExplosionProcess::move_entity( const tripoint position, std::get>( cur_target ), new_angle, new_velocity, cur_relative_time ) ); } -}; +} void ExplosionProcess::run() { diff --git a/src/faction.cpp b/src/faction.cpp index 2ef3bc0c64cf..6c41972600c4 100644 --- a/src/faction.cpp +++ b/src/faction.cpp @@ -112,7 +112,7 @@ faction_template::faction_template( const JsonObject &jsobj ) } lone_wolf_faction = jsobj.get_bool( "lone_wolf_faction", false ); load_relations( jsobj ); - mon_faction = jsobj.get_string( "mon_faction", "human" ); + mon_faction = mfaction_str_id( jsobj.get_string( "mon_faction", "human" ) ); for( const JsonObject jao : jsobj.get_array( "epilogues" ) ) { epilogue_data.emplace( jao.get_int( "power_min", std::numeric_limits::min() ), jao.get_int( "power_max", std::numeric_limits::max() ), @@ -459,6 +459,24 @@ faction *faction_manager::get( const faction_id &id, const bool complain ) return nullptr; } +template<> +const faction &string_id::obj() const +{ + const faction *ptr = g->faction_manager_ptr->get( *this, true ); + if( ptr ) { + return *ptr; + } else { + static faction null_fac; + return null_fac; + } +} + +template<> +bool string_id::is_valid() const +{ + return g->faction_manager_ptr->get( *this, false ); +} + void basecamp::faction_display( const catacurses::window &fac_w, const int width ) const { int y = 2; diff --git a/src/faction.h b/src/faction.h index 15db441e0d6e..887ecca377b4 100644 --- a/src/faction.h +++ b/src/faction.h @@ -11,6 +11,7 @@ #include #include +#include "catalua_type_operators.h" #include "character_id.h" #include "color.h" #include "cursesdef.h" @@ -88,7 +89,7 @@ class faction_template bool lone_wolf_faction; // is this a faction for just one person? itype_id currency; // id of the faction currency std::map> relations; - std::string mon_faction; // mon_faction_id of the monster faction; defaults to human + mfaction_str_id mon_faction; // mon_faction_id of the monster faction; defaults to human std::set> epilogue_data; }; @@ -105,6 +106,8 @@ class faction : public faction_template std::string describe() const; std::vector epilogue() const; + LUA_TYPE_OPS( faction, id ); + std::string food_supply_text(); nc_color food_supply_color(); diff --git a/src/field_type.h b/src/field_type.h index 761d29cc9c0f..1c5387ef59a9 100644 --- a/src/field_type.h +++ b/src/field_type.h @@ -15,6 +15,7 @@ #include "bodypart.h" #include "calendar.h" #include "catacharset.h" +#include "catalua_type_operators.h" #include "color.h" #include "effect.h" #include "enums.h" @@ -184,6 +185,8 @@ struct field_type { fields::stacking_type stacking_type = fields::stacking_type::intensity; + LUA_TYPE_OPS( field_type, id ); + public: const field_intensity_level &get_intensity_level( int level = 0 ) const; std::string get_name( int level = 0 ) const { diff --git a/src/game.cpp b/src/game.cpp index b14910ea7873..83262c5851a4 100644 --- a/src/game.cpp +++ b/src/game.cpp @@ -46,6 +46,7 @@ #include "basecamp.h" #include "bionics.h" #include "bodypart.h" +#include "calendar.h" #include "cata_utility.h" #include "catacharset.h" #include "character.h" @@ -1524,6 +1525,8 @@ bool game::do_turn() mon_info_update(); u.process_turn(); + cata::run_on_every_x_hooks( *DynamicDataLoader::get_instance().lua ); + explosion_handler::get_explosion_queue().execute(); cleanup_dead(); @@ -2214,6 +2217,8 @@ input_context get_default_mode_input_context() ctxt.register_action( "open_color" ); ctxt.register_action( "open_world_mods" ); ctxt.register_action( "debug" ); + ctxt.register_action( "lua_console" ); + ctxt.register_action( "lua_reload" ); ctxt.register_action( "debug_scent" ); ctxt.register_action( "debug_scent_type" ); ctxt.register_action( "debug_temp" ); @@ -2628,6 +2633,10 @@ bool game::load( const save_t &name ) u.reset(); + cata::load_world_lua_state( get_world_base_save_path() + "/lua_state.json" ); + + cata::run_on_game_load_hooks( *DynamicDataLoader::get_instance().lua ); + return true; } @@ -2737,8 +2746,17 @@ spell_events &game::spell_events_subscriber() return *spell_events_ptr; } +static bool save_uistate_data( const game &g ) +{ + return write_to_file( g.get_world_base_save_path() + "/uistate.json", [&]( std::ostream & fout ) { + JsonOut jsout( fout ); + uistate.serialize( jsout ); + }, _( "uistate data" ) ); +} + bool game::save( bool quitting ) { + cata::run_on_game_save_hooks( *DynamicDataLoader::get_instance().lua ); try { reset_save_ids( time( nullptr ), quitting ); if( !save_factions_missions_npcs() || @@ -2748,10 +2766,9 @@ bool game::save( bool quitting ) !get_auto_pickup().save_character() || !get_auto_notes_settings().save() || !get_safemode().save_character() || - !write_to_file( get_world_base_save_path() + "/uistate.json", [&]( std::ostream & fout ) { - JsonOut jsout( fout ); - uistate.serialize( jsout ); - }, _( "uistate data" ) ) ) { + !cata::save_world_lua_state( g->get_world_base_save_path() + "/lua_state.json" ) || + !save_uistate_data( *this ) + ) { return false; } else { world_generator->last_world_name = world_generator->active_world->world_name; diff --git a/src/generic_factory.h b/src/generic_factory.h index fe1720ddc663..434245c62ada 100644 --- a/src/generic_factory.h +++ b/src/generic_factory.h @@ -705,7 +705,8 @@ inline bool handle_proportional( const JsonObject &jo, const std::string &name, JsonObject proportional = jo.get_object( "proportional" ); proportional.allow_omitted_members(); if( proportional.has_member( name ) ) { - debugmsg( "Member %s of type %s does not support proportional", name, typeid( MemberType ).name() ); + debugmsg( "Member %s of type %s does not support proportional", name, + demangle( typeid( MemberType ).name() ) ); } } return false; @@ -755,7 +756,8 @@ inline bool handle_relative( const JsonObject &jo, const std::string &name, Memb if( !relative.has_member( name ) ) { return false; } - debugmsg( "Member %s of type %s does not support relative", name, typeid( MemberType ).name() ); + debugmsg( "Member %s of type %s does not support relative", name, + demangle( typeid( MemberType ).name() ) ); } return false; } diff --git a/src/generic_readers.h b/src/generic_readers.h index 639bc3e35b8e..4f5948fdc3b8 100644 --- a/src/generic_readers.h +++ b/src/generic_readers.h @@ -248,7 +248,7 @@ class generic_typed_reader if( !relative.has_member( name ) ) { return false; } - debugmsg( "Member %s of type %s does not support relative", name, typeid( C ).name() ); + debugmsg( "Member %s of type %s does not support relative", name, demangle( typeid( C ).name() ) ); } return false; } diff --git a/src/handle_action.cpp b/src/handle_action.cpp index a12ebb2ae9c9..61bd6bb8e071 100644 --- a/src/handle_action.cpp +++ b/src/handle_action.cpp @@ -19,6 +19,7 @@ #include "bionics.h" #include "bionics_ui.h" #include "calendar.h" +#include "catalua.h" #include "catacharset.h" #include "character.h" #include "character_display.h" @@ -2383,6 +2384,14 @@ bool game::handle_action() debug_menu::debug(); break; + case ACTION_LUA_CONSOLE: + cata::show_lua_console(); + break; + + case ACTION_LUA_RELOAD: + cata::reload_lua_code(); + break; + case ACTION_TOGGLE_FULLSCREEN: toggle_fullscreen(); break; diff --git a/src/init.cpp b/src/init.cpp index 07cf8b1032e7..ba62b1d4453a 100644 --- a/src/init.cpp +++ b/src/init.cpp @@ -21,6 +21,7 @@ #include "behavior.h" #include "bionics.h" #include "bodypart.h" +#include "catalua.h" #include "cata_utility.h" #include "clothing_mod.h" #include "clzones.h" @@ -635,6 +636,10 @@ void DynamicDataLoader::unload_data() #if defined(TILES) reset_mod_tileset(); #endif + + // Has to be cleaned last in case one of the above data collections + // holds references to Lua functions or tables. + lua.reset(); } void DynamicDataLoader::finalize_loaded_data( loading_ui &ui ) @@ -720,9 +725,6 @@ void DynamicDataLoader::finalize_loaded_data( loading_ui &ui ) e.second(); ui.proceed(); } - - check_consistency( ui ); - finalized = true; } void DynamicDataLoader::check_consistency( loading_ui &ui ) @@ -816,6 +818,8 @@ void DynamicDataLoader::check_consistency( loading_ui &ui ) e.second(); ui.proceed(); } + + finalized = true; } /** @@ -846,13 +850,68 @@ static void load_and_finalize_packs( loading_ui &ui, const std::string &msg, DynamicDataLoader &loader = DynamicDataLoader::get_instance(); + loader.lua = cata::make_wrapped_state(); + + cata::init_global_state_tables( *loader.lua, available ); + ui.show(); + for( const mod_id &mod : available ) { + if( mod->lua_api_version ) { + if( !cata::has_lua() ) { + throw std::runtime_error( + string_format( + "You need game build with Lua support to load content pack %s [%s]", + mod->name(), mod + ) + ); + } + if( cata::get_lua_api_version() != *mod->lua_api_version ) { + // The mod may be broken, but let's be user-friendly and try to load it anyway + debugmsg( + "Content pack uses outdated Lua API (current: %d, uses: %d) %s [%s]", + cata::get_lua_api_version(), *mod->lua_api_version, + mod->name(), mod + ); + } + cata::set_mod_being_loaded( *loader.lua, mod ); + cata::run_mod_preload_script( *loader.lua, mod ); + } + } + + cata::reg_lua_iuse_actors( *loader.lua, *item_controller ); + for( const mod_id &mod : available ) { loader.load_data_from_path( mod->path, mod.str(), ui ); ui.proceed(); } loader.finalize_loaded_data( ui ); + + if( cata::has_lua() ) { + for( const mod_id &mod : available ) { + if( mod->lua_api_version ) { + cata::set_mod_being_loaded( *loader.lua, mod ); + cata::run_mod_finalize_script( *loader.lua, mod ); + } + } + } + + loader.check_consistency( ui ); + + if( cata::has_lua() ) { + init::load_main_lua_scripts( *loader.lua, packs ); + cata::clear_mod_being_loaded( *loader.lua ); + } +} + +void init::load_main_lua_scripts( cata::lua_state &state, const std::vector &packs ) +{ + for( const mod_id &mod : packs ) { + if( mod.is_valid() && mod->lua_api_version ) { + cata::set_mod_being_loaded( state, mod ); + cata::run_mod_main_script( state, mod ); + } + } } bool init::is_data_loaded() @@ -932,14 +991,19 @@ bool init::check_mods_for_errors( loading_ui &ui, const std::vector &opt return false; } + if( id->lua_api_version && !cata::has_lua() ) { + std::cerr << string_format( "Mod requires Lua support: [%s]\n", id ); + return false; + } + to_check.emplace( id ); } // If no specific mods specified check all non-obsolete mods if( to_check.empty() ) { - for( const mod_id &e : world_generator->get_mod_manager().all_mods() ) { - if( !e->obsolete ) { - to_check.emplace( e ); + for( const mod_id &mod : world_generator->get_mod_manager().all_mods() ) { + if( !mod->obsolete && !( !cata::has_lua() && mod->lua_api_version ) ) { + to_check.emplace( mod ); } } } diff --git a/src/init.h b/src/init.h index 39c59c4a7328..323d80ccfd7c 100644 --- a/src/init.h +++ b/src/init.h @@ -9,6 +9,7 @@ #include #include +#include "catalua.h" #include "json.h" #include "memory_fast.h" #include "type_id.h" @@ -67,6 +68,8 @@ class DynamicDataLoader */ using deferred_json = std::vector>; + std::unique_ptr lua; + private: bool finalized = false; @@ -111,6 +114,8 @@ class DynamicDataLoader * Initializes @ref type_function_map */ void initialize(); + + public: /** * Check the consistency of all the loaded data. * May print a debugmsg if something seems wrong. @@ -118,7 +123,6 @@ class DynamicDataLoader */ void check_consistency( loading_ui &ui ); - public: /** * Returns the single instance of this class. */ @@ -177,6 +181,9 @@ class DynamicDataLoader namespace init { +/** Load (or reload) mods' main Lua scripts. */ +void load_main_lua_scripts( cata::lua_state &state, const std::vector &packs ); + /** Returns whether the game data is currently loaded. */ bool is_data_loaded(); diff --git a/src/item.cpp b/src/item.cpp index 329a8202ffd1..7e5411e8938c 100644 --- a/src/item.cpp +++ b/src/item.cpp @@ -10407,25 +10407,38 @@ bool item::has_clothing_mod() const return false; } +namespace +{ +const std::string &get_clothing_mod_val_key( clothing_mod_type type ) +{ + const static auto cache = ( []() { + std::array res; + for( const clothing_mod_type &type : clothing_mods::all_clothing_mod_types ) { + res[type] = CLOTHING_MOD_VAR_PREFIX + + clothing_mods::string_from_clothing_mod_type( clothing_mods::all_clothing_mod_types[type] ); + } + return res; + } )(); + + return cache[ type ]; +} +} // namespace + float item::get_clothing_mod_val( clothing_mod_type type ) const { - const std::string key = CLOTHING_MOD_VAR_PREFIX + clothing_mods::string_from_clothing_mod_type( - type ); - return get_var( key, 0.0 ); + return get_var( get_clothing_mod_val_key( type ), 0.0f ); } void item::update_clothing_mod_val() { for( const clothing_mod_type &type : clothing_mods::all_clothing_mod_types ) { - const std::string key = CLOTHING_MOD_VAR_PREFIX + clothing_mods::string_from_clothing_mod_type( - type ); float tmp = 0.0; for( const clothing_mod &cm : clothing_mods::get_all_with( type ) ) { if( has_own_flag( cm.flag ) ) { tmp += cm.get_mod_val( type, *this ); } } - set_var( key, tmp ); + set_var( get_clothing_mod_val_key( type ), tmp ); } } diff --git a/src/item.h b/src/item.h index 5087ee843499..b0f4ac6642ce 100644 --- a/src/item.h +++ b/src/item.h @@ -1334,6 +1334,16 @@ class item : public location_visitable, public game_object void set_snippet( const snippet_id &id ); bool operator<( const item &other ) const; + + /** LUA: We need this operator defined for Lua bindings to compile. */ + inline bool operator==( const item &rhs ) const { + return this == &rhs; + }; + /** LUA: We need this operator defined for Lua bindings to compile. */ + inline bool operator<=( const item &other ) const { + return operator<( other ) || operator==( other ); + } + /** List of all @ref components in printable form, empty if this item has * no components */ std::string components_to_string() const; diff --git a/src/item_factory.cpp b/src/item_factory.cpp index cfdb7904a000..8426850e4492 100644 --- a/src/item_factory.cpp +++ b/src/item_factory.cpp @@ -1440,9 +1440,9 @@ void Item_factory::check_definitions() const } else if( !mag_ptr->magazine->type.count( ammo_variety.first ) ) { msg += string_format( "magazine \"%s\" does not take compatible ammo\n", magazine ); } else if( mag_ptr->has_flag( "SPEEDLOADER" ) && - mag_ptr->magazine->capacity != type->gun->clip ) { + mag_ptr->magazine->capacity > type->gun->clip ) { msg += string_format( - "speedloader %s capacity (%d) does not match gun capacity (%d).\n", + "speedloader %s capacity (%d) is bigger than gun capacity (%d).\n", magazine.str(), mag_ptr->magazine->capacity, type->gun->clip ); } } @@ -2460,6 +2460,7 @@ void Item_factory::load_basic_info( const JsonObject &jo, itype &def, const std: "GUNMOD", "MAGAZINE", "PET_ARMOR", + "SPECIES", "TOOL", "TOOLMOD", "TOOL_ARMOR", diff --git a/src/item_factory.h b/src/item_factory.h index 5f1dc9ed3d7d..bfe8ef31e64d 100644 --- a/src/item_factory.h +++ b/src/item_factory.h @@ -360,8 +360,10 @@ class Item_factory void add_iuse( const std::string &type, use_function_pointer f ); void add_iuse( const std::string &type, use_function_pointer f, const std::string &info ); + public: void add_actor( std::unique_ptr ); + private: std::map migrations; /** diff --git a/src/itype.h b/src/itype.h index 5daf0e503701..f3300e286ef3 100644 --- a/src/itype.h +++ b/src/itype.h @@ -14,6 +14,7 @@ #include "bodypart.h" // body_part::num_bp #include "calendar.h" +#include "catalua_type_operators.h" #include "color.h" // nc_color #include "damage.h" #include "enums.h" // point @@ -808,6 +809,8 @@ struct itype { std::vector> src; + LUA_TYPE_OPS( itype, id ); + /** * Slots for various item type properties. Each slot may contain a valid pointer or null, check * this before using it. diff --git a/src/iuse.cpp b/src/iuse.cpp index 37aea4fc1394..7a477dde827b 100644 --- a/src/iuse.cpp +++ b/src/iuse.cpp @@ -315,6 +315,7 @@ static const trait_id trait_MARLOSS_YELLOW( "MARLOSS_YELLOW" ); static const trait_id trait_MYOPIC( "MYOPIC" ); static const trait_id trait_NOPAIN( "NOPAIN" ); static const trait_id trait_POISRESIST( "POISRESIST" ); +static const trait_id trait_PROF_FERAL( "PROF_FERAL" ); static const trait_id trait_PSYCHOPATH( "PSYCHOPATH" ); static const trait_id trait_SAPROVORE( "SAPROVORE" ); static const trait_id trait_SPIRITUAL( "SPIRITUAL" ); @@ -1319,7 +1320,7 @@ static void marloss_common( player &p, item &it, const trait_id ¤t_color ) } else if( effect == 8 ) { p.add_msg_if_player( m_bad, _( "You take one bite, and immediately vomit!" ) ); p.vomit(); - } else if( p.crossed_threshold() ) { + } else if( p.crossed_threshold() || p.has_trait( trait_PROF_FERAL ) ) { // Mycus Rejection. Goo already present fights off the fungus. p.add_msg_if_player( m_bad, _( "You feel a familiar warmth, but suddenly it surges into an excruciating burn as you convulse, vomiting, and black out…" ) ); @@ -1592,6 +1593,15 @@ static int petfood( player &p, item &it, Petfood animal_food_type ) return 0; } + // Feral survivors don't get to tame normal critters. + if( p.has_trait( trait_PROF_FERAL ) ) { + // TODO: Allow player ferals to tame zombie animals, but make sure non-feral players + // can't tame them, and for flavor possibly only allow taming with meat-based items. + p.add_msg_if_player( _( "You reach for the %s, but it recoils away from you!" ), + mon.type->nname() ); + return 0; + } + // This switch handles each petfood for each type of tameable monster. switch( animal_food_type ) { case DOGFOOD: diff --git a/src/json_export.h b/src/json_export.h new file mode 100644 index 000000000000..8a44fcc63732 --- /dev/null +++ b/src/json_export.h @@ -0,0 +1,15 @@ +#pragma once +#ifndef CATA_SRC_JSON_EXPORT_H +#define CATA_SRC_JSON_EXPORT_H + +#include "json.h" + +class vehicle; + +namespace json_export +{ +auto vehicle( JsonOut &json, const vehicle &v ) -> void; + +} // namespace json_export + +#endif // CATA_SRC_JSON_EXPORT_H diff --git a/src/line.cpp b/src/line.cpp index eedb85632826..5ec0fc195149 100644 --- a/src/line.cpp +++ b/src/line.cpp @@ -553,6 +553,7 @@ std::string direction_suffix( const tripoint &p, const tripoint &q ) std::vector squares_closer_to( const tripoint &from, const tripoint &to ) { std::vector adjacent_closer_squares; + adjacent_closer_squares.reserve( 5 ); const tripoint d( -from + to ); const point a( std::abs( d.x ), std::abs( d.y ) ); if( d.z != 0 ) { @@ -591,6 +592,7 @@ std::vector squares_in_direction( point p1, point p2 ) int junk = 0; point center_square = line_to( p1, p2, junk )[0]; std::vector adjacent_squares; + adjacent_squares.reserve( 3 ); adjacent_squares.push_back( center_square ); if( p1.x == center_square.x ) { // Horizontally adjacent. diff --git a/src/lua/LICENSE.md b/src/lua/LICENSE.md new file mode 100644 index 000000000000..db78d02532bb --- /dev/null +++ b/src/lua/LICENSE.md @@ -0,0 +1,18 @@ +Copyright © 1994–2021 Lua.org, PUC-Rio. + +Permission is hereby granted, free of charge, to any person obtaining a copy of +this software and associated documentation files (the "Software"), to deal in +the Software without restriction, including without limitation the rights to +use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/src/lua/README.md b/src/lua/README.md new file mode 100644 index 000000000000..cd36506fcbdd --- /dev/null +++ b/src/lua/README.md @@ -0,0 +1,2 @@ + +This folder contains Lua 5.3.6 source code, to be compiled into the main game executable. diff --git a/src/lua/lapi.c b/src/lua/lapi.c new file mode 100644 index 000000000000..711895b395b6 --- /dev/null +++ b/src/lua/lapi.c @@ -0,0 +1,1299 @@ +/* +** $Id: lapi.c,v 2.259.1.2 2017/12/06 18:35:12 roberto Exp $ +** Lua API +** See Copyright Notice in lua.h +*/ + +#define lapi_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" + + + +const char lua_ident[] = + "$LuaVersion: " LUA_COPYRIGHT " $" + "$LuaAuthors: " LUA_AUTHORS " $"; + + +/* value at a non-valid index */ +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) + +/* corresponding test */ +#define isvalid(o) ((o) != luaO_nilobject) + +/* test for pseudo index */ +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) + +/* test for upvalue */ +#define isupvalue(i) ((i) < LUA_REGISTRYINDEX) + +/* test for valid but not pseudo index */ +#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) + +#define api_checkvalidindex(l,o) api_check(l, isvalid(o), "invalid index") + +#define api_checkstackindex(l, i, o) \ + api_check(l, isstackindex(i, o), "index not in the stack") + + +static TValue *index2addr (lua_State *L, int idx) { + CallInfo *ci = L->ci; + if (idx > 0) { + TValue *o = ci->func + idx; + api_check(L, idx <= ci->top - (ci->func + 1), "unacceptable index"); + if (o >= L->top) return NONVALIDVALUE; + else return o; + } + else if (!ispseudo(idx)) { /* negative index */ + api_check(L, idx != 0 && -idx <= L->top - (ci->func + 1), "invalid index"); + return L->top + idx; + } + else if (idx == LUA_REGISTRYINDEX) + return &G(L)->l_registry; + else { /* upvalues */ + idx = LUA_REGISTRYINDEX - idx; + api_check(L, idx <= MAXUPVAL + 1, "upvalue index too large"); + if (ttislcf(ci->func)) /* light C function? */ + return NONVALIDVALUE; /* it has no upvalues */ + else { + CClosure *func = clCvalue(ci->func); + return (idx <= func->nupvalues) ? &func->upvalue[idx-1] : NONVALIDVALUE; + } + } +} + + +/* +** to be called by 'lua_checkstack' in protected mode, to grow stack +** capturing memory errors +*/ +static void growstack (lua_State *L, void *ud) { + int size = *(int *)ud; + luaD_growstack(L, size); +} + + +LUA_API int lua_checkstack (lua_State *L, int n) { + int res; + CallInfo *ci = L->ci; + lua_lock(L); + api_check(L, n >= 0, "negative 'n'"); + if (L->stack_last - L->top > n) /* stack large enough? */ + res = 1; /* yes; check is OK */ + else { /* no; need to grow stack */ + int inuse = cast_int(L->top - L->stack) + EXTRA_STACK; + if (inuse > LUAI_MAXSTACK - n) /* can grow without overflow? */ + res = 0; /* no */ + else /* try to grow stack */ + res = (luaD_rawrunprotected(L, &growstack, &n) == LUA_OK); + } + if (res && ci->top < L->top + n) + ci->top = L->top + n; /* adjust frame top */ + lua_unlock(L); + return res; +} + + +LUA_API void lua_xmove (lua_State *from, lua_State *to, int n) { + int i; + if (from == to) return; + lua_lock(to); + api_checknelems(from, n); + api_check(from, G(from) == G(to), "moving among independent states"); + api_check(from, to->ci->top - to->top >= n, "stack overflow"); + from->top -= n; + for (i = 0; i < n; i++) { + setobj2s(to, to->top, from->top + i); + to->top++; /* stack already checked by previous 'api_check' */ + } + lua_unlock(to); +} + + +LUA_API lua_CFunction lua_atpanic (lua_State *L, lua_CFunction panicf) { + lua_CFunction old; + lua_lock(L); + old = G(L)->panic; + G(L)->panic = panicf; + lua_unlock(L); + return old; +} + + +LUA_API const lua_Number *lua_version (lua_State *L) { + static const lua_Number version = LUA_VERSION_NUM; + if (L == NULL) return &version; + else return G(L)->version; +} + + + +/* +** basic stack manipulation +*/ + + +/* +** convert an acceptable stack index into an absolute index +*/ +LUA_API int lua_absindex (lua_State *L, int idx) { + return (idx > 0 || ispseudo(idx)) + ? idx + : cast_int(L->top - L->ci->func) + idx; +} + + +LUA_API int lua_gettop (lua_State *L) { + return cast_int(L->top - (L->ci->func + 1)); +} + + +LUA_API void lua_settop (lua_State *L, int idx) { + StkId func = L->ci->func; + lua_lock(L); + if (idx >= 0) { + api_check(L, idx <= L->stack_last - (func + 1), "new top too large"); + while (L->top < (func + 1) + idx) + setnilvalue(L->top++); + L->top = (func + 1) + idx; + } + else { + api_check(L, -(idx+1) <= (L->top - (func + 1)), "invalid new top"); + L->top += idx+1; /* 'subtract' index (index is negative) */ + } + lua_unlock(L); +} + + +/* +** Reverse the stack segment from 'from' to 'to' +** (auxiliary to 'lua_rotate') +*/ +static void reverse (lua_State *L, StkId from, StkId to) { + for (; from < to; from++, to--) { + TValue temp; + setobj(L, &temp, from); + setobjs2s(L, from, to); + setobj2s(L, to, &temp); + } +} + + +/* +** Let x = AB, where A is a prefix of length 'n'. Then, +** rotate x n == BA. But BA == (A^r . B^r)^r. +*/ +LUA_API void lua_rotate (lua_State *L, int idx, int n) { + StkId p, t, m; + lua_lock(L); + t = L->top - 1; /* end of stack segment being rotated */ + p = index2addr(L, idx); /* start of segment */ + api_checkstackindex(L, idx, p); + api_check(L, (n >= 0 ? n : -n) <= (t - p + 1), "invalid 'n'"); + m = (n >= 0 ? t - n : p - n - 1); /* end of prefix */ + reverse(L, p, m); /* reverse the prefix with length 'n' */ + reverse(L, m + 1, t); /* reverse the suffix */ + reverse(L, p, t); /* reverse the entire segment */ + lua_unlock(L); +} + + +LUA_API void lua_copy (lua_State *L, int fromidx, int toidx) { + TValue *fr, *to; + lua_lock(L); + fr = index2addr(L, fromidx); + to = index2addr(L, toidx); + api_checkvalidindex(L, to); + setobj(L, to, fr); + if (isupvalue(toidx)) /* function upvalue? */ + luaC_barrier(L, clCvalue(L->ci->func), fr); + /* LUA_REGISTRYINDEX does not need gc barrier + (collector revisits it before finishing collection) */ + lua_unlock(L); +} + + +LUA_API void lua_pushvalue (lua_State *L, int idx) { + lua_lock(L); + setobj2s(L, L->top, index2addr(L, idx)); + api_incr_top(L); + lua_unlock(L); +} + + + +/* +** access functions (stack -> C) +*/ + + +LUA_API int lua_type (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return (isvalid(o) ? ttnov(o) : LUA_TNONE); +} + + +LUA_API const char *lua_typename (lua_State *L, int t) { + UNUSED(L); + api_check(L, LUA_TNONE <= t && t < LUA_NUMTAGS, "invalid tag"); + return ttypename(t); +} + + +LUA_API int lua_iscfunction (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return (ttislcf(o) || (ttisCclosure(o))); +} + + +LUA_API int lua_isinteger (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return ttisinteger(o); +} + + +LUA_API int lua_isnumber (lua_State *L, int idx) { + lua_Number n; + const TValue *o = index2addr(L, idx); + return tonumber(o, &n); +} + + +LUA_API int lua_isstring (lua_State *L, int idx) { + const TValue *o = index2addr(L, idx); + return (ttisstring(o) || cvt2str(o)); +} + + +LUA_API int lua_isuserdata (lua_State *L, int idx) { + const TValue *o = index2addr(L, idx); + return (ttisfulluserdata(o) || ttislightuserdata(o)); +} + + +LUA_API int lua_rawequal (lua_State *L, int index1, int index2) { + StkId o1 = index2addr(L, index1); + StkId o2 = index2addr(L, index2); + return (isvalid(o1) && isvalid(o2)) ? luaV_rawequalobj(o1, o2) : 0; +} + + +LUA_API void lua_arith (lua_State *L, int op) { + lua_lock(L); + if (op != LUA_OPUNM && op != LUA_OPBNOT) + api_checknelems(L, 2); /* all other operations expect two operands */ + else { /* for unary operations, add fake 2nd operand */ + api_checknelems(L, 1); + setobjs2s(L, L->top, L->top - 1); + api_incr_top(L); + } + /* first operand at top - 2, second at top - 1; result go to top - 2 */ + luaO_arith(L, op, L->top - 2, L->top - 1, L->top - 2); + L->top--; /* remove second operand */ + lua_unlock(L); +} + + +LUA_API int lua_compare (lua_State *L, int index1, int index2, int op) { + StkId o1, o2; + int i = 0; + lua_lock(L); /* may call tag method */ + o1 = index2addr(L, index1); + o2 = index2addr(L, index2); + if (isvalid(o1) && isvalid(o2)) { + switch (op) { + case LUA_OPEQ: i = luaV_equalobj(L, o1, o2); break; + case LUA_OPLT: i = luaV_lessthan(L, o1, o2); break; + case LUA_OPLE: i = luaV_lessequal(L, o1, o2); break; + default: api_check(L, 0, "invalid option"); + } + } + lua_unlock(L); + return i; +} + + +LUA_API size_t lua_stringtonumber (lua_State *L, const char *s) { + size_t sz = luaO_str2num(s, L->top); + if (sz != 0) + api_incr_top(L); + return sz; +} + + +LUA_API lua_Number lua_tonumberx (lua_State *L, int idx, int *pisnum) { + lua_Number n; + const TValue *o = index2addr(L, idx); + int isnum = tonumber(o, &n); + if (!isnum) + n = 0; /* call to 'tonumber' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return n; +} + + +LUA_API lua_Integer lua_tointegerx (lua_State *L, int idx, int *pisnum) { + lua_Integer res; + const TValue *o = index2addr(L, idx); + int isnum = tointeger(o, &res); + if (!isnum) + res = 0; /* call to 'tointeger' may change 'n' even if it fails */ + if (pisnum) *pisnum = isnum; + return res; +} + + +LUA_API int lua_toboolean (lua_State *L, int idx) { + const TValue *o = index2addr(L, idx); + return !l_isfalse(o); +} + + +LUA_API const char *lua_tolstring (lua_State *L, int idx, size_t *len) { + StkId o = index2addr(L, idx); + if (!ttisstring(o)) { + if (!cvt2str(o)) { /* not convertible? */ + if (len != NULL) *len = 0; + return NULL; + } + lua_lock(L); /* 'luaO_tostring' may create a new string */ + luaO_tostring(L, o); + luaC_checkGC(L); + o = index2addr(L, idx); /* previous call may reallocate the stack */ + lua_unlock(L); + } + if (len != NULL) + *len = vslen(o); + return svalue(o); +} + + +LUA_API size_t lua_rawlen (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttype(o)) { + case LUA_TSHRSTR: return tsvalue(o)->shrlen; + case LUA_TLNGSTR: return tsvalue(o)->u.lnglen; + case LUA_TUSERDATA: return uvalue(o)->len; + case LUA_TTABLE: return luaH_getn(hvalue(o)); + default: return 0; + } +} + + +LUA_API lua_CFunction lua_tocfunction (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + if (ttislcf(o)) return fvalue(o); + else if (ttisCclosure(o)) + return clCvalue(o)->f; + else return NULL; /* not a C function */ +} + + +LUA_API void *lua_touserdata (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttnov(o)) { + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + +LUA_API lua_State *lua_tothread (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + return (!ttisthread(o)) ? NULL : thvalue(o); +} + + +LUA_API const void *lua_topointer (lua_State *L, int idx) { + StkId o = index2addr(L, idx); + switch (ttype(o)) { + case LUA_TTABLE: return hvalue(o); + case LUA_TLCL: return clLvalue(o); + case LUA_TCCL: return clCvalue(o); + case LUA_TLCF: return cast(void *, cast(size_t, fvalue(o))); + case LUA_TTHREAD: return thvalue(o); + case LUA_TUSERDATA: return getudatamem(uvalue(o)); + case LUA_TLIGHTUSERDATA: return pvalue(o); + default: return NULL; + } +} + + + +/* +** push functions (C -> stack) +*/ + + +LUA_API void lua_pushnil (lua_State *L) { + lua_lock(L); + setnilvalue(L->top); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushnumber (lua_State *L, lua_Number n) { + lua_lock(L); + setfltvalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushinteger (lua_State *L, lua_Integer n) { + lua_lock(L); + setivalue(L->top, n); + api_incr_top(L); + lua_unlock(L); +} + + +/* +** Pushes on the stack a string with given length. Avoid using 's' when +** 'len' == 0 (as 's' can be NULL in that case), due to later use of +** 'memcmp' and 'memcpy'. +*/ +LUA_API const char *lua_pushlstring (lua_State *L, const char *s, size_t len) { + TString *ts; + lua_lock(L); + ts = (len == 0) ? luaS_new(L, "") : luaS_newlstr(L, s, len); + setsvalue2s(L, L->top, ts); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getstr(ts); +} + + +LUA_API const char *lua_pushstring (lua_State *L, const char *s) { + lua_lock(L); + if (s == NULL) + setnilvalue(L->top); + else { + TString *ts; + ts = luaS_new(L, s); + setsvalue2s(L, L->top, ts); + s = getstr(ts); /* internal copy's address */ + } + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return s; +} + + +LUA_API const char *lua_pushvfstring (lua_State *L, const char *fmt, + va_list argp) { + const char *ret; + lua_lock(L); + ret = luaO_pushvfstring(L, fmt, argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; +} + + +LUA_API const char *lua_pushfstring (lua_State *L, const char *fmt, ...) { + const char *ret; + va_list argp; + lua_lock(L); + va_start(argp, fmt); + ret = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + luaC_checkGC(L); + lua_unlock(L); + return ret; +} + + +LUA_API void lua_pushcclosure (lua_State *L, lua_CFunction fn, int n) { + lua_lock(L); + if (n == 0) { + setfvalue(L->top, fn); + api_incr_top(L); + } + else { + CClosure *cl; + api_checknelems(L, n); + api_check(L, n <= MAXUPVAL, "upvalue index too large"); + cl = luaF_newCclosure(L, n); + cl->f = fn; + L->top -= n; + while (n--) { + setobj2n(L, &cl->upvalue[n], L->top + n); + /* does not need barrier because closure is white */ + } + setclCvalue(L, L->top, cl); + api_incr_top(L); + luaC_checkGC(L); + } + lua_unlock(L); +} + + +LUA_API void lua_pushboolean (lua_State *L, int b) { + lua_lock(L); + setbvalue(L->top, (b != 0)); /* ensure that true is 1 */ + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API void lua_pushlightuserdata (lua_State *L, void *p) { + lua_lock(L); + setpvalue(L->top, p); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API int lua_pushthread (lua_State *L) { + lua_lock(L); + setthvalue(L, L->top, L); + api_incr_top(L); + lua_unlock(L); + return (G(L)->mainthread == L); +} + + + +/* +** get functions (Lua -> stack) +*/ + + +static int auxgetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + if (luaV_fastget(L, t, str, slot, luaH_getstr)) { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else { + setsvalue2s(L, L->top, str); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); + } + lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API int lua_getglobal (lua_State *L, const char *name) { + Table *reg = hvalue(&G(L)->l_registry); + lua_lock(L); + return auxgetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +} + + +LUA_API int lua_gettable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_gettable(L, t, L->top - 1, L->top - 1); + lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API int lua_getfield (lua_State *L, int idx, const char *k) { + lua_lock(L); + return auxgetstr(L, index2addr(L, idx), k); +} + + +LUA_API int lua_geti (lua_State *L, int idx, lua_Integer n) { + StkId t; + const TValue *slot; + lua_lock(L); + t = index2addr(L, idx); + if (luaV_fastget(L, t, n, slot, luaH_getint)) { + setobj2s(L, L->top, slot); + api_incr_top(L); + } + else { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishget(L, t, L->top - 1, L->top - 1, slot); + } + lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API int lua_rawget (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top - 1, luaH_get(hvalue(t), L->top - 1)); + lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API int lua_rawgeti (lua_State *L, int idx, lua_Integer n) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setobj2s(L, L->top, luaH_getint(hvalue(t), n)); + api_incr_top(L); + lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API int lua_rawgetp (lua_State *L, int idx, const void *p) { + StkId t; + TValue k; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + setpvalue(&k, cast(void *, p)); + setobj2s(L, L->top, luaH_get(hvalue(t), &k)); + api_incr_top(L); + lua_unlock(L); + return ttnov(L->top - 1); +} + + +LUA_API void lua_createtable (lua_State *L, int narray, int nrec) { + Table *t; + lua_lock(L); + t = luaH_new(L); + sethvalue(L, L->top, t); + api_incr_top(L); + if (narray > 0 || nrec > 0) + luaH_resize(L, t, narray, nrec); + luaC_checkGC(L); + lua_unlock(L); +} + + +LUA_API int lua_getmetatable (lua_State *L, int objindex) { + const TValue *obj; + Table *mt; + int res = 0; + lua_lock(L); + obj = index2addr(L, objindex); + switch (ttnov(obj)) { + case LUA_TTABLE: + mt = hvalue(obj)->metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(obj)->metatable; + break; + default: + mt = G(L)->mt[ttnov(obj)]; + break; + } + if (mt != NULL) { + sethvalue(L, L->top, mt); + api_incr_top(L); + res = 1; + } + lua_unlock(L); + return res; +} + + +LUA_API int lua_getuservalue (lua_State *L, int idx) { + StkId o; + lua_lock(L); + o = index2addr(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + getuservalue(L, uvalue(o), L->top); + api_incr_top(L); + lua_unlock(L); + return ttnov(L->top - 1); +} + + +/* +** set functions (stack -> Lua) +*/ + +/* +** t[k] = value at the top of the stack (where 'k' is a string) +*/ +static void auxsetstr (lua_State *L, const TValue *t, const char *k) { + const TValue *slot; + TString *str = luaS_new(L, k); + api_checknelems(L, 1); + if (luaV_fastset(L, t, str, slot, luaH_getstr, L->top - 1)) + L->top--; /* pop value */ + else { + setsvalue2s(L, L->top, str); /* push 'str' (to make it a TValue) */ + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); /* lock done by caller */ +} + + +LUA_API void lua_setglobal (lua_State *L, const char *name) { + Table *reg = hvalue(&G(L)->l_registry); + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, luaH_getint(reg, LUA_RIDX_GLOBALS), name); +} + + +LUA_API void lua_settable (lua_State *L, int idx) { + StkId t; + lua_lock(L); + api_checknelems(L, 2); + t = index2addr(L, idx); + luaV_settable(L, t, L->top - 2, L->top - 1); + L->top -= 2; /* pop index and value */ + lua_unlock(L); +} + + +LUA_API void lua_setfield (lua_State *L, int idx, const char *k) { + lua_lock(L); /* unlock done in 'auxsetstr' */ + auxsetstr(L, index2addr(L, idx), k); +} + + +LUA_API void lua_seti (lua_State *L, int idx, lua_Integer n) { + StkId t; + const TValue *slot; + lua_lock(L); + api_checknelems(L, 1); + t = index2addr(L, idx); + if (luaV_fastset(L, t, n, slot, luaH_getint, L->top - 1)) + L->top--; /* pop value */ + else { + setivalue(L->top, n); + api_incr_top(L); + luaV_finishset(L, t, L->top - 1, L->top - 2, slot); + L->top -= 2; /* pop value and key */ + } + lua_unlock(L); +} + + +LUA_API void lua_rawset (lua_State *L, int idx) { + StkId o; + TValue *slot; + lua_lock(L); + api_checknelems(L, 2); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + slot = luaH_set(L, hvalue(o), L->top - 2); + setobj2t(L, slot, L->top - 1); + invalidateTMcache(hvalue(o)); + luaC_barrierback(L, hvalue(o), L->top-1); + L->top -= 2; + lua_unlock(L); +} + + +LUA_API void lua_rawseti (lua_State *L, int idx, lua_Integer n) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + luaH_setint(L, hvalue(o), n, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top-1); + L->top--; + lua_unlock(L); +} + + +LUA_API void lua_rawsetp (lua_State *L, int idx, const void *p) { + StkId o; + TValue k, *slot; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttistable(o), "table expected"); + setpvalue(&k, cast(void *, p)); + slot = luaH_set(L, hvalue(o), &k); + setobj2t(L, slot, L->top - 1); + luaC_barrierback(L, hvalue(o), L->top - 1); + L->top--; + lua_unlock(L); +} + + +LUA_API int lua_setmetatable (lua_State *L, int objindex) { + TValue *obj; + Table *mt; + lua_lock(L); + api_checknelems(L, 1); + obj = index2addr(L, objindex); + if (ttisnil(L->top - 1)) + mt = NULL; + else { + api_check(L, ttistable(L->top - 1), "table expected"); + mt = hvalue(L->top - 1); + } + switch (ttnov(obj)) { + case LUA_TTABLE: { + hvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, gcvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + case LUA_TUSERDATA: { + uvalue(obj)->metatable = mt; + if (mt) { + luaC_objbarrier(L, uvalue(obj), mt); + luaC_checkfinalizer(L, gcvalue(obj), mt); + } + break; + } + default: { + G(L)->mt[ttnov(obj)] = mt; + break; + } + } + L->top--; + lua_unlock(L); + return 1; +} + + +LUA_API void lua_setuservalue (lua_State *L, int idx) { + StkId o; + lua_lock(L); + api_checknelems(L, 1); + o = index2addr(L, idx); + api_check(L, ttisfulluserdata(o), "full userdata expected"); + setuservalue(L, uvalue(o), L->top - 1); + luaC_barrier(L, gcvalue(o), L->top - 1); + L->top--; + lua_unlock(L); +} + + +/* +** 'load' and 'call' functions (run Lua code) +*/ + + +#define checkresults(L,na,nr) \ + api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ + "results from function overflow current stack size") + + +LUA_API void lua_callk (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k) { + StkId func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + func = L->top - (nargs+1); + if (k != NULL && L->nny == 0) { /* need to prepare continuation? */ + L->ci->u.c.k = k; /* save continuation */ + L->ci->u.c.ctx = ctx; /* save context */ + luaD_call(L, func, nresults); /* do the call */ + } + else /* no continuation or no yieldable */ + luaD_callnoyield(L, func, nresults); /* just do the call */ + adjustresults(L, nresults); + lua_unlock(L); +} + + + +/* +** Execute a protected call. +*/ +struct CallS { /* data to 'f_call' */ + StkId func; + int nresults; +}; + + +static void f_call (lua_State *L, void *ud) { + struct CallS *c = cast(struct CallS *, ud); + luaD_callnoyield(L, c->func, c->nresults); +} + + + +LUA_API int lua_pcallk (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k) { + struct CallS c; + int status; + ptrdiff_t func; + lua_lock(L); + api_check(L, k == NULL || !isLua(L->ci), + "cannot use continuations inside hooks"); + api_checknelems(L, nargs+1); + api_check(L, L->status == LUA_OK, "cannot do calls on non-normal thread"); + checkresults(L, nargs, nresults); + if (errfunc == 0) + func = 0; + else { + StkId o = index2addr(L, errfunc); + api_checkstackindex(L, errfunc, o); + func = savestack(L, o); + } + c.func = L->top - (nargs+1); /* function to be called */ + if (k == NULL || L->nny > 0) { /* no continuation or no yieldable? */ + c.nresults = nresults; /* do a 'conventional' protected call */ + status = luaD_pcall(L, f_call, &c, savestack(L, c.func), func); + } + else { /* prepare continuation (call is already protected by 'resume') */ + CallInfo *ci = L->ci; + ci->u.c.k = k; /* save continuation */ + ci->u.c.ctx = ctx; /* save context */ + /* save information for error recovery */ + ci->extra = savestack(L, c.func); + ci->u.c.old_errfunc = L->errfunc; + L->errfunc = func; + setoah(ci->callstatus, L->allowhook); /* save value of 'allowhook' */ + ci->callstatus |= CIST_YPCALL; /* function can do error recovery */ + luaD_call(L, c.func, nresults); /* do the call */ + ci->callstatus &= ~CIST_YPCALL; + L->errfunc = ci->u.c.old_errfunc; + status = LUA_OK; /* if it is here, there were no errors */ + } + adjustresults(L, nresults); + lua_unlock(L); + return status; +} + + +LUA_API int lua_load (lua_State *L, lua_Reader reader, void *data, + const char *chunkname, const char *mode) { + ZIO z; + int status; + lua_lock(L); + if (!chunkname) chunkname = "?"; + luaZ_init(L, &z, reader, data); + status = luaD_protectedparser(L, &z, chunkname, mode); + if (status == LUA_OK) { /* no errors? */ + LClosure *f = clLvalue(L->top - 1); /* get newly created function */ + if (f->nupvalues >= 1) { /* does it have an upvalue? */ + /* get global table from registry */ + Table *reg = hvalue(&G(L)->l_registry); + const TValue *gt = luaH_getint(reg, LUA_RIDX_GLOBALS); + /* set global table as 1st upvalue of 'f' (may be LUA_ENV) */ + setobj(L, f->upvals[0]->v, gt); + luaC_upvalbarrier(L, f->upvals[0]); + } + } + lua_unlock(L); + return status; +} + + +LUA_API int lua_dump (lua_State *L, lua_Writer writer, void *data, int strip) { + int status; + TValue *o; + lua_lock(L); + api_checknelems(L, 1); + o = L->top - 1; + if (isLfunction(o)) + status = luaU_dump(L, getproto(o), writer, data, strip); + else + status = 1; + lua_unlock(L); + return status; +} + + +LUA_API int lua_status (lua_State *L) { + return L->status; +} + + +/* +** Garbage-collection function +*/ + +LUA_API int lua_gc (lua_State *L, int what, int data) { + int res = 0; + global_State *g; + lua_lock(L); + g = G(L); + switch (what) { + case LUA_GCSTOP: { + g->gcrunning = 0; + break; + } + case LUA_GCRESTART: { + luaE_setdebt(g, 0); + g->gcrunning = 1; + break; + } + case LUA_GCCOLLECT: { + luaC_fullgc(L, 0); + break; + } + case LUA_GCCOUNT: { + /* GC values are expressed in Kbytes: #bytes/2^10 */ + res = cast_int(gettotalbytes(g) >> 10); + break; + } + case LUA_GCCOUNTB: { + res = cast_int(gettotalbytes(g) & 0x3ff); + break; + } + case LUA_GCSTEP: { + l_mem debt = 1; /* =1 to signal that it did an actual step */ + lu_byte oldrunning = g->gcrunning; + g->gcrunning = 1; /* allow GC to run */ + if (data == 0) { + luaE_setdebt(g, -GCSTEPSIZE); /* to do a "small" step */ + luaC_step(L); + } + else { /* add 'data' to total debt */ + debt = cast(l_mem, data) * 1024 + g->GCdebt; + luaE_setdebt(g, debt); + luaC_checkGC(L); + } + g->gcrunning = oldrunning; /* restore previous state */ + if (debt > 0 && g->gcstate == GCSpause) /* end of cycle? */ + res = 1; /* signal it */ + break; + } + case LUA_GCSETPAUSE: { + res = g->gcpause; + g->gcpause = data; + break; + } + case LUA_GCSETSTEPMUL: { + res = g->gcstepmul; + if (data < 40) data = 40; /* avoid ridiculous low values (and 0) */ + g->gcstepmul = data; + break; + } + case LUA_GCISRUNNING: { + res = g->gcrunning; + break; + } + default: res = -1; /* invalid option */ + } + lua_unlock(L); + return res; +} + + + +/* +** miscellaneous functions +*/ + + +LUA_API int lua_error (lua_State *L) { + lua_lock(L); + api_checknelems(L, 1); + luaG_errormsg(L); + /* code unreachable; will unlock when control actually leaves the kernel */ + return 0; /* to avoid warnings */ +} + + +LUA_API int lua_next (lua_State *L, int idx) { + StkId t; + int more; + lua_lock(L); + t = index2addr(L, idx); + api_check(L, ttistable(t), "table expected"); + more = luaH_next(L, hvalue(t), L->top - 1); + if (more) { + api_incr_top(L); + } + else /* no more elements */ + L->top -= 1; /* remove key */ + lua_unlock(L); + return more; +} + + +LUA_API void lua_concat (lua_State *L, int n) { + lua_lock(L); + api_checknelems(L, n); + if (n >= 2) { + luaV_concat(L, n); + } + else if (n == 0) { /* push empty string */ + setsvalue2s(L, L->top, luaS_newlstr(L, "", 0)); + api_incr_top(L); + } + /* else n == 1; nothing to do */ + luaC_checkGC(L); + lua_unlock(L); +} + + +LUA_API void lua_len (lua_State *L, int idx) { + StkId t; + lua_lock(L); + t = index2addr(L, idx); + luaV_objlen(L, L->top, t); + api_incr_top(L); + lua_unlock(L); +} + + +LUA_API lua_Alloc lua_getallocf (lua_State *L, void **ud) { + lua_Alloc f; + lua_lock(L); + if (ud) *ud = G(L)->ud; + f = G(L)->frealloc; + lua_unlock(L); + return f; +} + + +LUA_API void lua_setallocf (lua_State *L, lua_Alloc f, void *ud) { + lua_lock(L); + G(L)->ud = ud; + G(L)->frealloc = f; + lua_unlock(L); +} + + +LUA_API void *lua_newuserdata (lua_State *L, size_t size) { + Udata *u; + lua_lock(L); + u = luaS_newudata(L, size); + setuvalue(L, L->top, u); + api_incr_top(L); + luaC_checkGC(L); + lua_unlock(L); + return getudatamem(u); +} + + + +static const char *aux_upvalue (StkId fi, int n, TValue **val, + CClosure **owner, UpVal **uv) { + switch (ttype(fi)) { + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + if (!(1 <= n && n <= f->nupvalues)) return NULL; + *val = &f->upvalue[n-1]; + if (owner) *owner = f; + return ""; + } + case LUA_TLCL: { /* Lua closure */ + LClosure *f = clLvalue(fi); + TString *name; + Proto *p = f->p; + if (!(1 <= n && n <= p->sizeupvalues)) return NULL; + *val = f->upvals[n-1]->v; + if (uv) *uv = f->upvals[n - 1]; + name = p->upvalues[n-1].name; + return (name == NULL) ? "(*no name)" : getstr(name); + } + default: return NULL; /* not a closure */ + } +} + + +LUA_API const char *lua_getupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + lua_lock(L); + name = aux_upvalue(index2addr(L, funcindex), n, &val, NULL, NULL); + if (name) { + setobj2s(L, L->top, val); + api_incr_top(L); + } + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setupvalue (lua_State *L, int funcindex, int n) { + const char *name; + TValue *val = NULL; /* to avoid warnings */ + CClosure *owner = NULL; + UpVal *uv = NULL; + StkId fi; + lua_lock(L); + fi = index2addr(L, funcindex); + api_checknelems(L, 1); + name = aux_upvalue(fi, n, &val, &owner, &uv); + if (name) { + L->top--; + setobj(L, val, L->top); + if (owner) { luaC_barrier(L, owner, L->top); } + else if (uv) { luaC_upvalbarrier(L, uv); } + } + lua_unlock(L); + return name; +} + + +static UpVal **getupvalref (lua_State *L, int fidx, int n) { + LClosure *f; + StkId fi = index2addr(L, fidx); + api_check(L, ttisLclosure(fi), "Lua function expected"); + f = clLvalue(fi); + api_check(L, (1 <= n && n <= f->p->sizeupvalues), "invalid upvalue index"); + return &f->upvals[n - 1]; /* get its upvalue pointer */ +} + + +LUA_API void *lua_upvalueid (lua_State *L, int fidx, int n) { + StkId fi = index2addr(L, fidx); + switch (ttype(fi)) { + case LUA_TLCL: { /* lua closure */ + return *getupvalref(L, fidx, n); + } + case LUA_TCCL: { /* C closure */ + CClosure *f = clCvalue(fi); + api_check(L, 1 <= n && n <= f->nupvalues, "invalid upvalue index"); + return &f->upvalue[n - 1]; + } + default: { + api_check(L, 0, "closure expected"); + return NULL; + } + } +} + + +LUA_API void lua_upvaluejoin (lua_State *L, int fidx1, int n1, + int fidx2, int n2) { + UpVal **up1 = getupvalref(L, fidx1, n1); + UpVal **up2 = getupvalref(L, fidx2, n2); + if (*up1 == *up2) + return; + luaC_upvdeccount(L, *up1); + *up1 = *up2; + (*up1)->refcount++; + if (upisopen(*up1)) (*up1)->u.open.touched = 1; + luaC_upvalbarrier(L, *up1); +} + + diff --git a/src/lua/lapi.h b/src/lua/lapi.h new file mode 100644 index 000000000000..8e16ad53d999 --- /dev/null +++ b/src/lua/lapi.h @@ -0,0 +1,24 @@ +/* +** $Id: lapi.h,v 2.9.1.1 2017/04/19 17:20:42 roberto Exp $ +** Auxiliary functions from Lua API +** See Copyright Notice in lua.h +*/ + +#ifndef lapi_h +#define lapi_h + + +#include "llimits.h" +#include "lstate.h" + +#define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ + "stack overflow");} + +#define adjustresults(L,nres) \ + { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } + +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") + + +#endif diff --git a/src/lua/lauxlib.c b/src/lua/lauxlib.c new file mode 100644 index 000000000000..ac68bd32da90 --- /dev/null +++ b/src/lua/lauxlib.c @@ -0,0 +1,1048 @@ +/* +** $Id: lauxlib.c,v 1.289.1.1 2017/04/19 17:20:42 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + +#define lauxlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + + +/* +** This file uses only the official API of Lua. +** Any function declared here could be written as an application function. +*/ + +#include "lua.h" + +#include "lauxlib.h" + + +/* +** {====================================================== +** Traceback +** ======================================================= +*/ + + +#define LEVELS1 10 /* size of the first part of the stack */ +#define LEVELS2 11 /* size of the second part of the stack */ + + + +/* +** search for 'objidx' in table at index -1. +** return 1 + string at top if find a good name. +*/ +static int findfield (lua_State *L, int objidx, int level) { + if (level == 0 || !lua_istable(L, -1)) + return 0; /* not found */ + lua_pushnil(L); /* start 'next' loop */ + while (lua_next(L, -2)) { /* for each pair in table */ + if (lua_type(L, -2) == LUA_TSTRING) { /* ignore non-string keys */ + if (lua_rawequal(L, objidx, -1)) { /* found object? */ + lua_pop(L, 1); /* remove value (but keep name) */ + return 1; + } + else if (findfield(L, objidx, level - 1)) { /* try recursively */ + lua_remove(L, -2); /* remove table (but keep name) */ + lua_pushliteral(L, "."); + lua_insert(L, -2); /* place '.' between the two names */ + lua_concat(L, 3); + return 1; + } + } + lua_pop(L, 1); /* remove value */ + } + return 0; /* not found */ +} + + +/* +** Search for a name for a function in all loaded modules +*/ +static int pushglobalfuncname (lua_State *L, lua_Debug *ar) { + int top = lua_gettop(L); + lua_getinfo(L, "f", ar); /* push function */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + if (findfield(L, top + 1, 2)) { + const char *name = lua_tostring(L, -1); + if (strncmp(name, "_G.", 3) == 0) { /* name start with '_G.'? */ + lua_pushstring(L, name + 3); /* push name without prefix */ + lua_remove(L, -2); /* remove original name */ + } + lua_copy(L, -1, top + 1); /* move name to proper place */ + lua_pop(L, 2); /* remove pushed values */ + return 1; + } + else { + lua_settop(L, top); /* remove function and global table */ + return 0; + } +} + + +static void pushfuncname (lua_State *L, lua_Debug *ar) { + if (pushglobalfuncname(L, ar)) { /* try first a global name */ + lua_pushfstring(L, "function '%s'", lua_tostring(L, -1)); + lua_remove(L, -2); /* remove name */ + } + else if (*ar->namewhat != '\0') /* is there a name from code? */ + lua_pushfstring(L, "%s '%s'", ar->namewhat, ar->name); /* use it */ + else if (*ar->what == 'm') /* main? */ + lua_pushliteral(L, "main chunk"); + else if (*ar->what != 'C') /* for Lua functions, use */ + lua_pushfstring(L, "function <%s:%d>", ar->short_src, ar->linedefined); + else /* nothing left... */ + lua_pushliteral(L, "?"); +} + + +static int lastlevel (lua_State *L) { + lua_Debug ar; + int li = 1, le = 1; + /* find an upper bound */ + while (lua_getstack(L, le, &ar)) { li = le; le *= 2; } + /* do a binary search */ + while (li < le) { + int m = (li + le)/2; + if (lua_getstack(L, m, &ar)) li = m + 1; + else le = m; + } + return le - 1; +} + + +LUALIB_API void luaL_traceback (lua_State *L, lua_State *L1, + const char *msg, int level) { + lua_Debug ar; + int top = lua_gettop(L); + int last = lastlevel(L1); + int n1 = (last - level > LEVELS1 + LEVELS2) ? LEVELS1 : -1; + if (msg) + lua_pushfstring(L, "%s\n", msg); + luaL_checkstack(L, 10, NULL); + lua_pushliteral(L, "stack traceback:"); + while (lua_getstack(L1, level++, &ar)) { + if (n1-- == 0) { /* too many levels? */ + lua_pushliteral(L, "\n\t..."); /* add a '...' */ + level = last - LEVELS2 + 1; /* and skip to last ones */ + } + else { + lua_getinfo(L1, "Slnt", &ar); + lua_pushfstring(L, "\n\t%s:", ar.short_src); + if (ar.currentline > 0) + lua_pushfstring(L, "%d:", ar.currentline); + lua_pushliteral(L, " in "); + pushfuncname(L, &ar); + if (ar.istailcall) + lua_pushliteral(L, "\n\t(...tail calls...)"); + lua_concat(L, lua_gettop(L) - top); + } + } + lua_concat(L, lua_gettop(L) - top); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Error-report functions +** ======================================================= +*/ + +LUALIB_API int luaL_argerror (lua_State *L, int arg, const char *extramsg) { + lua_Debug ar; + if (!lua_getstack(L, 0, &ar)) /* no stack frame? */ + return luaL_error(L, "bad argument #%d (%s)", arg, extramsg); + lua_getinfo(L, "n", &ar); + if (strcmp(ar.namewhat, "method") == 0) { + arg--; /* do not count 'self' */ + if (arg == 0) /* error is in the self argument itself? */ + return luaL_error(L, "calling '%s' on bad self (%s)", + ar.name, extramsg); + } + if (ar.name == NULL) + ar.name = (pushglobalfuncname(L, &ar)) ? lua_tostring(L, -1) : "?"; + return luaL_error(L, "bad argument #%d to '%s' (%s)", + arg, ar.name, extramsg); +} + + +static int typeerror (lua_State *L, int arg, const char *tname) { + const char *msg; + const char *typearg; /* name for the type of the actual argument */ + if (luaL_getmetafield(L, arg, "__name") == LUA_TSTRING) + typearg = lua_tostring(L, -1); /* use the given type name */ + else if (lua_type(L, arg) == LUA_TLIGHTUSERDATA) + typearg = "light userdata"; /* special name for messages */ + else + typearg = luaL_typename(L, arg); /* standard name */ + msg = lua_pushfstring(L, "%s expected, got %s", tname, typearg); + return luaL_argerror(L, arg, msg); +} + + +static void tag_error (lua_State *L, int arg, int tag) { + typeerror(L, arg, lua_typename(L, tag)); +} + + +/* +** The use of 'lua_pushfstring' ensures this function does not +** need reserved stack space when called. +*/ +LUALIB_API void luaL_where (lua_State *L, int level) { + lua_Debug ar; + if (lua_getstack(L, level, &ar)) { /* check function at level */ + lua_getinfo(L, "Sl", &ar); /* get info about it */ + if (ar.currentline > 0) { /* is there info? */ + lua_pushfstring(L, "%s:%d: ", ar.short_src, ar.currentline); + return; + } + } + lua_pushfstring(L, ""); /* else, no information available... */ +} + + +/* +** Again, the use of 'lua_pushvfstring' ensures this function does +** not need reserved stack space when called. (At worst, it generates +** an error with "stack overflow" instead of the given message.) +*/ +LUALIB_API int luaL_error (lua_State *L, const char *fmt, ...) { + va_list argp; + va_start(argp, fmt); + luaL_where(L, 1); + lua_pushvfstring(L, fmt, argp); + va_end(argp); + lua_concat(L, 2); + return lua_error(L); +} + + +LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { + int en = errno; /* calls to Lua API may change this value */ + if (stat) { + lua_pushboolean(L, 1); + return 1; + } + else { + lua_pushnil(L); + if (fname) + lua_pushfstring(L, "%s: %s", fname, strerror(en)); + else + lua_pushstring(L, strerror(en)); + lua_pushinteger(L, en); + return 3; + } +} + + +#if !defined(l_inspectstat) /* { */ + +#if defined(LUA_USE_POSIX) + +#include + +/* +** use appropriate macros to interpret 'pclose' return status +*/ +#define l_inspectstat(stat,what) \ + if (WIFEXITED(stat)) { stat = WEXITSTATUS(stat); } \ + else if (WIFSIGNALED(stat)) { stat = WTERMSIG(stat); what = "signal"; } + +#else + +#define l_inspectstat(stat,what) /* no op */ + +#endif + +#endif /* } */ + + +LUALIB_API int luaL_execresult (lua_State *L, int stat) { + const char *what = "exit"; /* type of termination */ + if (stat == -1) /* error? */ + return luaL_fileresult(L, 0, NULL); + else { + l_inspectstat(stat, what); /* interpret result */ + if (*what == 'e' && stat == 0) /* successful termination? */ + lua_pushboolean(L, 1); + else + lua_pushnil(L); + lua_pushstring(L, what); + lua_pushinteger(L, stat); + return 3; /* return true/nil,what,code */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Userdata's metatable manipulation +** ======================================================= +*/ + +LUALIB_API int luaL_newmetatable (lua_State *L, const char *tname) { + if (luaL_getmetatable(L, tname) != LUA_TNIL) /* name already in use? */ + return 0; /* leave previous value on top, but return 0 */ + lua_pop(L, 1); + lua_createtable(L, 0, 2); /* create metatable */ + lua_pushstring(L, tname); + lua_setfield(L, -2, "__name"); /* metatable.__name = tname */ + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, tname); /* registry.name = metatable */ + return 1; +} + + +LUALIB_API void luaL_setmetatable (lua_State *L, const char *tname) { + luaL_getmetatable(L, tname); + lua_setmetatable(L, -2); +} + + +LUALIB_API void *luaL_testudata (lua_State *L, int ud, const char *tname) { + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + luaL_getmetatable(L, tname); /* get correct metatable */ + if (!lua_rawequal(L, -1, -2)) /* not the same? */ + p = NULL; /* value is a userdata with wrong metatable */ + lua_pop(L, 2); /* remove both metatables */ + return p; + } + } + return NULL; /* value is not a userdata with a metatable */ +} + + +LUALIB_API void *luaL_checkudata (lua_State *L, int ud, const char *tname) { + void *p = luaL_testudata(L, ud, tname); + if (p == NULL) typeerror(L, ud, tname); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Argument check functions +** ======================================================= +*/ + +LUALIB_API int luaL_checkoption (lua_State *L, int arg, const char *def, + const char *const lst[]) { + const char *name = (def) ? luaL_optstring(L, arg, def) : + luaL_checkstring(L, arg); + int i; + for (i=0; lst[i]; i++) + if (strcmp(lst[i], name) == 0) + return i; + return luaL_argerror(L, arg, + lua_pushfstring(L, "invalid option '%s'", name)); +} + + +/* +** Ensures the stack has at least 'space' extra slots, raising an error +** if it cannot fulfill the request. (The error handling needs a few +** extra slots to format the error message. In case of an error without +** this extra space, Lua will generate the same 'stack overflow' error, +** but without 'msg'.) +*/ +LUALIB_API void luaL_checkstack (lua_State *L, int space, const char *msg) { + if (!lua_checkstack(L, space)) { + if (msg) + luaL_error(L, "stack overflow (%s)", msg); + else + luaL_error(L, "stack overflow"); + } +} + + +LUALIB_API void luaL_checktype (lua_State *L, int arg, int t) { + if (lua_type(L, arg) != t) + tag_error(L, arg, t); +} + + +LUALIB_API void luaL_checkany (lua_State *L, int arg) { + if (lua_type(L, arg) == LUA_TNONE) + luaL_argerror(L, arg, "value expected"); +} + + +LUALIB_API const char *luaL_checklstring (lua_State *L, int arg, size_t *len) { + const char *s = lua_tolstring(L, arg, len); + if (!s) tag_error(L, arg, LUA_TSTRING); + return s; +} + + +LUALIB_API const char *luaL_optlstring (lua_State *L, int arg, + const char *def, size_t *len) { + if (lua_isnoneornil(L, arg)) { + if (len) + *len = (def ? strlen(def) : 0); + return def; + } + else return luaL_checklstring(L, arg, len); +} + + +LUALIB_API lua_Number luaL_checknumber (lua_State *L, int arg) { + int isnum; + lua_Number d = lua_tonumberx(L, arg, &isnum); + if (!isnum) + tag_error(L, arg, LUA_TNUMBER); + return d; +} + + +LUALIB_API lua_Number luaL_optnumber (lua_State *L, int arg, lua_Number def) { + return luaL_opt(L, luaL_checknumber, arg, def); +} + + +static void interror (lua_State *L, int arg) { + if (lua_isnumber(L, arg)) + luaL_argerror(L, arg, "number has no integer representation"); + else + tag_error(L, arg, LUA_TNUMBER); +} + + +LUALIB_API lua_Integer luaL_checkinteger (lua_State *L, int arg) { + int isnum; + lua_Integer d = lua_tointegerx(L, arg, &isnum); + if (!isnum) { + interror(L, arg); + } + return d; +} + + +LUALIB_API lua_Integer luaL_optinteger (lua_State *L, int arg, + lua_Integer def) { + return luaL_opt(L, luaL_checkinteger, arg, def); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +/* userdata to box arbitrary data */ +typedef struct UBox { + void *box; + size_t bsize; +} UBox; + + +static void *resizebox (lua_State *L, int idx, size_t newsize) { + void *ud; + lua_Alloc allocf = lua_getallocf(L, &ud); + UBox *box = (UBox *)lua_touserdata(L, idx); + void *temp = allocf(ud, box->box, box->bsize, newsize); + if (temp == NULL && newsize > 0) { /* allocation error? */ + resizebox(L, idx, 0); /* free buffer */ + luaL_error(L, "not enough memory for buffer allocation"); + } + box->box = temp; + box->bsize = newsize; + return temp; +} + + +static int boxgc (lua_State *L) { + resizebox(L, 1, 0); + return 0; +} + + +static void *newbox (lua_State *L, size_t newsize) { + UBox *box = (UBox *)lua_newuserdata(L, sizeof(UBox)); + box->box = NULL; + box->bsize = 0; + if (luaL_newmetatable(L, "LUABOX")) { /* creating metatable? */ + lua_pushcfunction(L, boxgc); + lua_setfield(L, -2, "__gc"); /* metatable.__gc = boxgc */ + } + lua_setmetatable(L, -2); + return resizebox(L, -1, newsize); +} + + +/* +** check whether buffer is using a userdata on the stack as a temporary +** buffer +*/ +#define buffonstack(B) ((B)->b != (B)->initb) + + +/* +** returns a pointer to a free area with at least 'sz' bytes +*/ +LUALIB_API char *luaL_prepbuffsize (luaL_Buffer *B, size_t sz) { + lua_State *L = B->L; + if (B->size - B->n < sz) { /* not enough space? */ + char *newbuff; + size_t newsize = B->size * 2; /* double buffer size */ + if (newsize - B->n < sz) /* not big enough? */ + newsize = B->n + sz; + if (newsize < B->n || newsize - B->n < sz) + luaL_error(L, "buffer too large"); + /* create larger buffer */ + if (buffonstack(B)) + newbuff = (char *)resizebox(L, -1, newsize); + else { /* no buffer yet */ + newbuff = (char *)newbox(L, newsize); + memcpy(newbuff, B->b, B->n * sizeof(char)); /* copy original content */ + } + B->b = newbuff; + B->size = newsize; + } + return &B->b[B->n]; +} + + +LUALIB_API void luaL_addlstring (luaL_Buffer *B, const char *s, size_t l) { + if (l > 0) { /* avoid 'memcpy' when 's' can be NULL */ + char *b = luaL_prepbuffsize(B, l); + memcpy(b, s, l * sizeof(char)); + luaL_addsize(B, l); + } +} + + +LUALIB_API void luaL_addstring (luaL_Buffer *B, const char *s) { + luaL_addlstring(B, s, strlen(s)); +} + + +LUALIB_API void luaL_pushresult (luaL_Buffer *B) { + lua_State *L = B->L; + lua_pushlstring(L, B->b, B->n); + if (buffonstack(B)) { + resizebox(L, -2, 0); /* delete old buffer */ + lua_remove(L, -2); /* remove its header from the stack */ + } +} + + +LUALIB_API void luaL_pushresultsize (luaL_Buffer *B, size_t sz) { + luaL_addsize(B, sz); + luaL_pushresult(B); +} + + +LUALIB_API void luaL_addvalue (luaL_Buffer *B) { + lua_State *L = B->L; + size_t l; + const char *s = lua_tolstring(L, -1, &l); + if (buffonstack(B)) + lua_insert(L, -2); /* put value below buffer */ + luaL_addlstring(B, s, l); + lua_remove(L, (buffonstack(B)) ? -2 : -1); /* remove value */ +} + + +LUALIB_API void luaL_buffinit (lua_State *L, luaL_Buffer *B) { + B->L = L; + B->b = B->initb; + B->n = 0; + B->size = LUAL_BUFFERSIZE; +} + + +LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { + luaL_buffinit(L, B); + return luaL_prepbuffsize(B, sz); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Reference system +** ======================================================= +*/ + +/* index of free-list header */ +#define freelist 0 + + +LUALIB_API int luaL_ref (lua_State *L, int t) { + int ref; + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* remove from stack */ + return LUA_REFNIL; /* 'nil' has a unique fixed reference */ + } + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); /* get first free element */ + ref = (int)lua_tointeger(L, -1); /* ref = t[freelist] */ + lua_pop(L, 1); /* remove it from stack */ + if (ref != 0) { /* any free element? */ + lua_rawgeti(L, t, ref); /* remove it from list */ + lua_rawseti(L, t, freelist); /* (t[freelist] = t[ref]) */ + } + else /* no free elements */ + ref = (int)lua_rawlen(L, t) + 1; /* get a new reference */ + lua_rawseti(L, t, ref); + return ref; +} + + +LUALIB_API void luaL_unref (lua_State *L, int t, int ref) { + if (ref >= 0) { + t = lua_absindex(L, t); + lua_rawgeti(L, t, freelist); + lua_rawseti(L, t, ref); /* t[ref] = t[freelist] */ + lua_pushinteger(L, ref); + lua_rawseti(L, t, freelist); /* t[freelist] = ref */ + } +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Load functions +** ======================================================= +*/ + +typedef struct LoadF { + int n; /* number of pre-read characters */ + FILE *f; /* file being read */ + char buff[BUFSIZ]; /* area for reading file */ +} LoadF; + + +static const char *getF (lua_State *L, void *ud, size_t *size) { + LoadF *lf = (LoadF *)ud; + (void)L; /* not used */ + if (lf->n > 0) { /* are there pre-read characters to be read? */ + *size = lf->n; /* return them (chars already in buffer) */ + lf->n = 0; /* no more pre-read characters */ + } + else { /* read a block from file */ + /* 'fread' can return > 0 *and* set the EOF flag. If next call to + 'getF' called 'fread', it might still wait for user input. + The next check avoids this problem. */ + if (feof(lf->f)) return NULL; + *size = fread(lf->buff, 1, sizeof(lf->buff), lf->f); /* read block */ + } + return lf->buff; +} + + +static int errfile (lua_State *L, const char *what, int fnameindex) { + const char *serr = strerror(errno); + const char *filename = lua_tostring(L, fnameindex) + 1; + lua_pushfstring(L, "cannot %s %s: %s", what, filename, serr); + lua_remove(L, fnameindex); + return LUA_ERRFILE; +} + + +static int skipBOM (LoadF *lf) { + const char *p = "\xEF\xBB\xBF"; /* UTF-8 BOM mark */ + int c; + lf->n = 0; + do { + c = getc(lf->f); + if (c == EOF || c != *(const unsigned char *)p++) return c; + lf->buff[lf->n++] = c; /* to be read by the parser */ + } while (*p != '\0'); + lf->n = 0; /* prefix matched; discard it */ + return getc(lf->f); /* return next character */ +} + + +/* +** reads the first character of file 'f' and skips an optional BOM mark +** in its beginning plus its first line if it starts with '#'. Returns +** true if it skipped the first line. In any case, '*cp' has the +** first "valid" character of the file (after the optional BOM and +** a first-line comment). +*/ +static int skipcomment (LoadF *lf, int *cp) { + int c = *cp = skipBOM(lf); + if (c == '#') { /* first line is a comment (Unix exec. file)? */ + do { /* skip first line */ + c = getc(lf->f); + } while (c != EOF && c != '\n'); + *cp = getc(lf->f); /* skip end-of-line, if present */ + return 1; /* there was a comment */ + } + else return 0; /* no comment */ +} + + +LUALIB_API int luaL_loadfilex (lua_State *L, const char *filename, + const char *mode) { + LoadF lf; + int status, readstatus; + int c; + int fnameindex = lua_gettop(L) + 1; /* index of filename on the stack */ + if (filename == NULL) { + lua_pushliteral(L, "=stdin"); + lf.f = stdin; + } + else { + lua_pushfstring(L, "@%s", filename); + lf.f = fopen(filename, "r"); + if (lf.f == NULL) return errfile(L, "open", fnameindex); + } + if (skipcomment(&lf, &c)) /* read initial portion */ + lf.buff[lf.n++] = '\n'; /* add line to correct line numbers */ + if (c == LUA_SIGNATURE[0] && filename) { /* binary file? */ + lf.f = freopen(filename, "rb", lf.f); /* reopen in binary mode */ + if (lf.f == NULL) return errfile(L, "reopen", fnameindex); + skipcomment(&lf, &c); /* re-read initial portion */ + } + if (c != EOF) + lf.buff[lf.n++] = c; /* 'c' is the first character of the stream */ + status = lua_load(L, getF, &lf, lua_tostring(L, -1), mode); + readstatus = ferror(lf.f); + if (filename) fclose(lf.f); /* close file (even in case of errors) */ + if (readstatus) { + lua_settop(L, fnameindex); /* ignore results from 'lua_load' */ + return errfile(L, "read", fnameindex); + } + lua_remove(L, fnameindex); + return status; +} + + +typedef struct LoadS { + const char *s; + size_t size; +} LoadS; + + +static const char *getS (lua_State *L, void *ud, size_t *size) { + LoadS *ls = (LoadS *)ud; + (void)L; /* not used */ + if (ls->size == 0) return NULL; + *size = ls->size; + ls->size = 0; + return ls->s; +} + + +LUALIB_API int luaL_loadbufferx (lua_State *L, const char *buff, size_t size, + const char *name, const char *mode) { + LoadS ls; + ls.s = buff; + ls.size = size; + return lua_load(L, getS, &ls, name, mode); +} + + +LUALIB_API int luaL_loadstring (lua_State *L, const char *s) { + return luaL_loadbuffer(L, s, strlen(s), s); +} + +/* }====================================================== */ + + + +LUALIB_API int luaL_getmetafield (lua_State *L, int obj, const char *event) { + if (!lua_getmetatable(L, obj)) /* no metatable? */ + return LUA_TNIL; + else { + int tt; + lua_pushstring(L, event); + tt = lua_rawget(L, -2); + if (tt == LUA_TNIL) /* is metafield nil? */ + lua_pop(L, 2); /* remove metatable and metafield */ + else + lua_remove(L, -2); /* remove only metatable */ + return tt; /* return metafield type */ + } +} + + +LUALIB_API int luaL_callmeta (lua_State *L, int obj, const char *event) { + obj = lua_absindex(L, obj); + if (luaL_getmetafield(L, obj, event) == LUA_TNIL) /* no metafield? */ + return 0; + lua_pushvalue(L, obj); + lua_call(L, 1, 1); + return 1; +} + + +LUALIB_API lua_Integer luaL_len (lua_State *L, int idx) { + lua_Integer l; + int isnum; + lua_len(L, idx); + l = lua_tointegerx(L, -1, &isnum); + if (!isnum) + luaL_error(L, "object length is not an integer"); + lua_pop(L, 1); /* remove object */ + return l; +} + + +LUALIB_API const char *luaL_tolstring (lua_State *L, int idx, size_t *len) { + if (luaL_callmeta(L, idx, "__tostring")) { /* metafield? */ + if (!lua_isstring(L, -1)) + luaL_error(L, "'__tostring' must return a string"); + } + else { + switch (lua_type(L, idx)) { + case LUA_TNUMBER: { + if (lua_isinteger(L, idx)) + lua_pushfstring(L, "%I", (LUAI_UACINT)lua_tointeger(L, idx)); + else + lua_pushfstring(L, "%f", (LUAI_UACNUMBER)lua_tonumber(L, idx)); + break; + } + case LUA_TSTRING: + lua_pushvalue(L, idx); + break; + case LUA_TBOOLEAN: + lua_pushstring(L, (lua_toboolean(L, idx) ? "true" : "false")); + break; + case LUA_TNIL: + lua_pushliteral(L, "nil"); + break; + default: { + int tt = luaL_getmetafield(L, idx, "__name"); /* try name */ + const char *kind = (tt == LUA_TSTRING) ? lua_tostring(L, -1) : + luaL_typename(L, idx); + lua_pushfstring(L, "%s: %p", kind, lua_topointer(L, idx)); + if (tt != LUA_TNIL) + lua_remove(L, -2); /* remove '__name' */ + break; + } + } + } + return lua_tolstring(L, -1, len); +} + + +/* +** {====================================================== +** Compatibility with 5.1 module functions +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +static const char *luaL_findtable (lua_State *L, int idx, + const char *fname, int szhint) { + const char *e; + if (idx) lua_pushvalue(L, idx); + do { + e = strchr(fname, '.'); + if (e == NULL) e = fname + strlen(fname); + lua_pushlstring(L, fname, e - fname); + if (lua_rawget(L, -2) == LUA_TNIL) { /* no such field? */ + lua_pop(L, 1); /* remove this nil */ + lua_createtable(L, 0, (*e == '.' ? 1 : szhint)); /* new table for field */ + lua_pushlstring(L, fname, e - fname); + lua_pushvalue(L, -2); + lua_settable(L, -4); /* set new table into field */ + } + else if (!lua_istable(L, -1)) { /* field has a non-table value? */ + lua_pop(L, 2); /* remove table and value */ + return fname; /* return problematic part of the name */ + } + lua_remove(L, -2); /* remove previous table */ + fname = e + 1; + } while (*e == '.'); + return NULL; +} + + +/* +** Count number of elements in a luaL_Reg list. +*/ +static int libsize (const luaL_Reg *l) { + int size = 0; + for (; l && l->name; l++) size++; + return size; +} + + +/* +** Find or create a module table with a given name. The function +** first looks at the LOADED table and, if that fails, try a +** global variable with that name. In any case, leaves on the stack +** the module table. +*/ +LUALIB_API void luaL_pushmodule (lua_State *L, const char *modname, + int sizehint) { + luaL_findtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE, 1); + if (lua_getfield(L, -1, modname) != LUA_TTABLE) { /* no LOADED[modname]? */ + lua_pop(L, 1); /* remove previous result */ + /* try global variable (and create one if it does not exist) */ + lua_pushglobaltable(L); + if (luaL_findtable(L, 0, modname, sizehint) != NULL) + luaL_error(L, "name conflict for module '%s'", modname); + lua_pushvalue(L, -1); + lua_setfield(L, -3, modname); /* LOADED[modname] = new table */ + } + lua_remove(L, -2); /* remove LOADED table */ +} + + +LUALIB_API void luaL_openlib (lua_State *L, const char *libname, + const luaL_Reg *l, int nup) { + luaL_checkversion(L); + if (libname) { + luaL_pushmodule(L, libname, libsize(l)); /* get/create library table */ + lua_insert(L, -(nup + 1)); /* move library table to below upvalues */ + } + if (l) + luaL_setfuncs(L, l, nup); + else + lua_pop(L, nup); /* remove upvalues */ +} + +#endif +/* }====================================================== */ + +/* +** set functions from list 'l' into table at top - 'nup'; each +** function gets the 'nup' elements at the top as upvalues. +** Returns with only the table at the stack. +*/ +LUALIB_API void luaL_setfuncs (lua_State *L, const luaL_Reg *l, int nup) { + luaL_checkstack(L, nup, "too many upvalues"); + for (; l->name != NULL; l++) { /* fill the table with given functions */ + int i; + for (i = 0; i < nup; i++) /* copy upvalues to the top */ + lua_pushvalue(L, -nup); + lua_pushcclosure(L, l->func, nup); /* closure with those upvalues */ + lua_setfield(L, -(nup + 2), l->name); + } + lua_pop(L, nup); /* remove upvalues */ +} + + +/* +** ensure that stack[idx][fname] has a table and push that table +** into the stack +*/ +LUALIB_API int luaL_getsubtable (lua_State *L, int idx, const char *fname) { + if (lua_getfield(L, idx, fname) == LUA_TTABLE) + return 1; /* table already there */ + else { + lua_pop(L, 1); /* remove previous result */ + idx = lua_absindex(L, idx); + lua_newtable(L); + lua_pushvalue(L, -1); /* copy to be left at top */ + lua_setfield(L, idx, fname); /* assign new table to field */ + return 0; /* false, because did not find table there */ + } +} + + +/* +** Stripped-down 'require': After checking "loaded" table, calls 'openf' +** to open a module, registers the result in 'package.loaded' table and, +** if 'glb' is true, also registers the result in the global table. +** Leaves resulting module on the top. +*/ +LUALIB_API void luaL_requiref (lua_State *L, const char *modname, + lua_CFunction openf, int glb) { + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, -1, modname); /* LOADED[modname] */ + if (!lua_toboolean(L, -1)) { /* package not already loaded? */ + lua_pop(L, 1); /* remove field */ + lua_pushcfunction(L, openf); + lua_pushstring(L, modname); /* argument to open function */ + lua_call(L, 1, 1); /* call 'openf' to open module */ + lua_pushvalue(L, -1); /* make copy of module (call result) */ + lua_setfield(L, -3, modname); /* LOADED[modname] = module */ + } + lua_remove(L, -2); /* remove LOADED table */ + if (glb) { + lua_pushvalue(L, -1); /* copy of module */ + lua_setglobal(L, modname); /* _G[modname] = module */ + } +} + + +LUALIB_API const char *luaL_gsub (lua_State *L, const char *s, const char *p, + const char *r) { + const char *wild; + size_t l = strlen(p); + luaL_Buffer b; + luaL_buffinit(L, &b); + while ((wild = strstr(s, p)) != NULL) { + luaL_addlstring(&b, s, wild - s); /* push prefix */ + luaL_addstring(&b, r); /* push replacement in place of pattern */ + s = wild + l; /* continue after 'p' */ + } + luaL_addstring(&b, s); /* push last suffix */ + luaL_pushresult(&b); + return lua_tostring(L, -1); +} + + +static void *l_alloc (void *ud, void *ptr, size_t osize, size_t nsize) { + (void)ud; (void)osize; /* not used */ + if (nsize == 0) { + free(ptr); + return NULL; + } + else { /* cannot fail when shrinking a block */ + void *newptr = realloc(ptr, nsize); + if (newptr == NULL && ptr != NULL && nsize <= osize) + return ptr; /* keep the original block */ + else /* no fail or not shrinking */ + return newptr; /* use the new block */ + } +} + + +static int panic (lua_State *L) { + lua_writestringerror("PANIC: unprotected error in call to Lua API (%s)\n", + lua_tostring(L, -1)); + return 0; /* return to Lua to abort */ +} + + +LUALIB_API lua_State *luaL_newstate (void) { + lua_State *L = lua_newstate(l_alloc, NULL); + if (L) lua_atpanic(L, &panic); + return L; +} + + +LUALIB_API void luaL_checkversion_ (lua_State *L, lua_Number ver, size_t sz) { + const lua_Number *v = lua_version(L); + if (sz != LUAL_NUMSIZES) /* check numeric types */ + luaL_error(L, "core and library have incompatible numeric types"); + if (v != lua_version(NULL)) + luaL_error(L, "multiple Lua VMs detected"); + else if (*v != ver) + luaL_error(L, "version mismatch: app. needs %f, Lua core provides %f", + (LUAI_UACNUMBER)ver, (LUAI_UACNUMBER)*v); +} + diff --git a/src/lua/lauxlib.h b/src/lua/lauxlib.h new file mode 100644 index 000000000000..9857d3a835a9 --- /dev/null +++ b/src/lua/lauxlib.h @@ -0,0 +1,264 @@ +/* +** $Id: lauxlib.h,v 1.131.1.1 2017/04/19 17:20:42 roberto Exp $ +** Auxiliary functions for building Lua libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lauxlib_h +#define lauxlib_h + + +#include +#include + +#include "lua.h" + + + +/* extra error code for 'luaL_loadfilex' */ +#define LUA_ERRFILE (LUA_ERRERR+1) + + +/* key, in the registry, for table of loaded modules */ +#define LUA_LOADED_TABLE "_LOADED" + + +/* key, in the registry, for table of preloaded loaders */ +#define LUA_PRELOAD_TABLE "_PRELOAD" + + +typedef struct luaL_Reg { + const char *name; + lua_CFunction func; +} luaL_Reg; + + +#define LUAL_NUMSIZES (sizeof(lua_Integer)*16 + sizeof(lua_Number)) + +LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver, size_t sz); +#define luaL_checkversion(L) \ + luaL_checkversion_(L, LUA_VERSION_NUM, LUAL_NUMSIZES) + +LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); +LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); +LUALIB_API const char *(luaL_tolstring) (lua_State *L, int idx, size_t *len); +LUALIB_API int (luaL_argerror) (lua_State *L, int arg, const char *extramsg); +LUALIB_API const char *(luaL_checklstring) (lua_State *L, int arg, + size_t *l); +LUALIB_API const char *(luaL_optlstring) (lua_State *L, int arg, + const char *def, size_t *l); +LUALIB_API lua_Number (luaL_checknumber) (lua_State *L, int arg); +LUALIB_API lua_Number (luaL_optnumber) (lua_State *L, int arg, lua_Number def); + +LUALIB_API lua_Integer (luaL_checkinteger) (lua_State *L, int arg); +LUALIB_API lua_Integer (luaL_optinteger) (lua_State *L, int arg, + lua_Integer def); + +LUALIB_API void (luaL_checkstack) (lua_State *L, int sz, const char *msg); +LUALIB_API void (luaL_checktype) (lua_State *L, int arg, int t); +LUALIB_API void (luaL_checkany) (lua_State *L, int arg); + +LUALIB_API int (luaL_newmetatable) (lua_State *L, const char *tname); +LUALIB_API void (luaL_setmetatable) (lua_State *L, const char *tname); +LUALIB_API void *(luaL_testudata) (lua_State *L, int ud, const char *tname); +LUALIB_API void *(luaL_checkudata) (lua_State *L, int ud, const char *tname); + +LUALIB_API void (luaL_where) (lua_State *L, int lvl); +LUALIB_API int (luaL_error) (lua_State *L, const char *fmt, ...); + +LUALIB_API int (luaL_checkoption) (lua_State *L, int arg, const char *def, + const char *const lst[]); + +LUALIB_API int (luaL_fileresult) (lua_State *L, int stat, const char *fname); +LUALIB_API int (luaL_execresult) (lua_State *L, int stat); + +/* predefined references */ +#define LUA_NOREF (-2) +#define LUA_REFNIL (-1) + +LUALIB_API int (luaL_ref) (lua_State *L, int t); +LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); + +LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, + const char *mode); + +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) + +LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, + const char *name, const char *mode); +LUALIB_API int (luaL_loadstring) (lua_State *L, const char *s); + +LUALIB_API lua_State *(luaL_newstate) (void); + +LUALIB_API lua_Integer (luaL_len) (lua_State *L, int idx); + +LUALIB_API const char *(luaL_gsub) (lua_State *L, const char *s, const char *p, + const char *r); + +LUALIB_API void (luaL_setfuncs) (lua_State *L, const luaL_Reg *l, int nup); + +LUALIB_API int (luaL_getsubtable) (lua_State *L, int idx, const char *fname); + +LUALIB_API void (luaL_traceback) (lua_State *L, lua_State *L1, + const char *msg, int level); + +LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, + lua_CFunction openf, int glb); + +/* +** =============================================================== +** some useful macros +** =============================================================== +*/ + + +#define luaL_newlibtable(L,l) \ + lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) + +#define luaL_newlib(L,l) \ + (luaL_checkversion(L), luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) + +#define luaL_argcheck(L, cond,arg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (arg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) + +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) + +#define luaL_dofile(L, fn) \ + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_dostring(L, s) \ + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) + +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) + +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) + + +/* +** {====================================================== +** Generic Buffer manipulation +** ======================================================= +*/ + +typedef struct luaL_Buffer { + char *b; /* buffer address */ + size_t size; /* buffer size */ + size_t n; /* number of characters in buffer */ + lua_State *L; + char initb[LUAL_BUFFERSIZE]; /* initial buffer */ +} luaL_Buffer; + + +#define luaL_addchar(B,c) \ + ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ + ((B)->b[(B)->n++] = (c))) + +#define luaL_addsize(B,s) ((B)->n += (s)) + +LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); +LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); +LUALIB_API void (luaL_addlstring) (luaL_Buffer *B, const char *s, size_t l); +LUALIB_API void (luaL_addstring) (luaL_Buffer *B, const char *s); +LUALIB_API void (luaL_addvalue) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); +LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); +LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); + +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) + +/* }====================================================== */ + + + +/* +** {====================================================== +** File handles for IO library +** ======================================================= +*/ + +/* +** A file handle is a userdata with metatable 'LUA_FILEHANDLE' and +** initial structure 'luaL_Stream' (it may contain other fields +** after that initial structure). +*/ + +#define LUA_FILEHANDLE "FILE*" + + +typedef struct luaL_Stream { + FILE *f; /* stream (NULL for incompletely created streams) */ + lua_CFunction closef; /* to close stream (NULL for closed streams) */ +} luaL_Stream; + +/* }====================================================== */ + + + +/* compatibility with old module system */ +#if defined(LUA_COMPAT_MODULE) + +LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, + int sizehint); +LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, + const luaL_Reg *l, int nup); + +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) + +#endif + + +/* +** {================================================================== +** "Abstraction Layer" for basic report of messages and errors +** =================================================================== +*/ + +/* print a string */ +#if !defined(lua_writestring) +#define lua_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#endif + +/* print a newline and flush the output */ +#if !defined(lua_writeline) +#define lua_writeline() (lua_writestring("\n", 1), fflush(stdout)) +#endif + +/* print an error message */ +#if !defined(lua_writestringerror) +#define lua_writestringerror(s,p) \ + (fprintf(stderr, (s), (p)), fflush(stderr)) +#endif + +/* }================================================================== */ + + +/* +** {============================================================ +** Compatibility with deprecated conversions +** ============================================================= +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define luaL_checkunsigned(L,a) ((lua_Unsigned)luaL_checkinteger(L,a)) +#define luaL_optunsigned(L,a,d) \ + ((lua_Unsigned)luaL_optinteger(L,a,(lua_Integer)(d))) + +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) + +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) + +#endif +/* }============================================================ */ + + + +#endif + + diff --git a/src/lua/lbaselib.c b/src/lua/lbaselib.c new file mode 100644 index 000000000000..6460e4f8d42b --- /dev/null +++ b/src/lua/lbaselib.c @@ -0,0 +1,498 @@ +/* +** $Id: lbaselib.c,v 1.314.1.1 2017/04/19 17:39:34 roberto Exp $ +** Basic library +** See Copyright Notice in lua.h +*/ + +#define lbaselib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static int luaB_print (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int i; + lua_getglobal(L, "tostring"); + for (i=1; i<=n; i++) { + const char *s; + size_t l; + lua_pushvalue(L, -1); /* function to be called */ + lua_pushvalue(L, i); /* value to print */ + lua_call(L, 1, 1); + s = lua_tolstring(L, -1, &l); /* get result */ + if (s == NULL) + return luaL_error(L, "'tostring' must return a string to 'print'"); + if (i>1) lua_writestring("\t", 1); + lua_writestring(s, l); + lua_pop(L, 1); /* pop result */ + } + lua_writeline(); + return 0; +} + + +#define SPACECHARS " \f\n\r\t\v" + +static const char *b_str2int (const char *s, int base, lua_Integer *pn) { + lua_Unsigned n = 0; + int neg = 0; + s += strspn(s, SPACECHARS); /* skip initial spaces */ + if (*s == '-') { s++; neg = 1; } /* handle signal */ + else if (*s == '+') s++; + if (!isalnum((unsigned char)*s)) /* no digit? */ + return NULL; + do { + int digit = (isdigit((unsigned char)*s)) ? *s - '0' + : (toupper((unsigned char)*s) - 'A') + 10; + if (digit >= base) return NULL; /* invalid numeral */ + n = n * base + digit; + s++; + } while (isalnum((unsigned char)*s)); + s += strspn(s, SPACECHARS); /* skip trailing spaces */ + *pn = (lua_Integer)((neg) ? (0u - n) : n); + return s; +} + + +static int luaB_tonumber (lua_State *L) { + if (lua_isnoneornil(L, 2)) { /* standard conversion? */ + luaL_checkany(L, 1); + if (lua_type(L, 1) == LUA_TNUMBER) { /* already a number? */ + lua_settop(L, 1); /* yes; return it */ + return 1; + } + else { + size_t l; + const char *s = lua_tolstring(L, 1, &l); + if (s != NULL && lua_stringtonumber(L, s) == l + 1) + return 1; /* successful conversion to number */ + /* else not a number */ + } + } + else { + size_t l; + const char *s; + lua_Integer n = 0; /* to avoid warnings */ + lua_Integer base = luaL_checkinteger(L, 2); + luaL_checktype(L, 1, LUA_TSTRING); /* no numbers as strings */ + s = lua_tolstring(L, 1, &l); + luaL_argcheck(L, 2 <= base && base <= 36, 2, "base out of range"); + if (b_str2int(s, (int)base, &n) == s + l) { + lua_pushinteger(L, n); + return 1; + } /* else not a number */ + } /* else not a number */ + lua_pushnil(L); /* not a number */ + return 1; +} + + +static int luaB_error (lua_State *L) { + int level = (int)luaL_optinteger(L, 2, 1); + lua_settop(L, 1); + if (lua_type(L, 1) == LUA_TSTRING && level > 0) { + luaL_where(L, level); /* add extra information */ + lua_pushvalue(L, 1); + lua_concat(L, 2); + } + return lua_error(L); +} + + +static int luaB_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); + return 1; /* no metatable */ + } + luaL_getmetafield(L, 1, "__metatable"); + return 1; /* returns either __metatable field (if present) or metatable */ +} + + +static int luaB_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_checktype(L, 1, LUA_TTABLE); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + if (luaL_getmetafield(L, 1, "__metatable") != LUA_TNIL) + return luaL_error(L, "cannot change a protected metatable"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; +} + + +static int luaB_rawequal (lua_State *L) { + luaL_checkany(L, 1); + luaL_checkany(L, 2); + lua_pushboolean(L, lua_rawequal(L, 1, 2)); + return 1; +} + + +static int luaB_rawlen (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t == LUA_TTABLE || t == LUA_TSTRING, 1, + "table or string expected"); + lua_pushinteger(L, lua_rawlen(L, 1)); + return 1; +} + + +static int luaB_rawget (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_rawget(L, 1); + return 1; +} + +static int luaB_rawset (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + luaL_checkany(L, 2); + luaL_checkany(L, 3); + lua_settop(L, 3); + lua_rawset(L, 1); + return 1; +} + + +static int luaB_collectgarbage (lua_State *L) { + static const char *const opts[] = {"stop", "restart", "collect", + "count", "step", "setpause", "setstepmul", + "isrunning", NULL}; + static const int optsnum[] = {LUA_GCSTOP, LUA_GCRESTART, LUA_GCCOLLECT, + LUA_GCCOUNT, LUA_GCSTEP, LUA_GCSETPAUSE, LUA_GCSETSTEPMUL, + LUA_GCISRUNNING}; + int o = optsnum[luaL_checkoption(L, 1, "collect", opts)]; + int ex = (int)luaL_optinteger(L, 2, 0); + int res = lua_gc(L, o, ex); + switch (o) { + case LUA_GCCOUNT: { + int b = lua_gc(L, LUA_GCCOUNTB, 0); + lua_pushnumber(L, (lua_Number)res + ((lua_Number)b/1024)); + return 1; + } + case LUA_GCSTEP: case LUA_GCISRUNNING: { + lua_pushboolean(L, res); + return 1; + } + default: { + lua_pushinteger(L, res); + return 1; + } + } +} + + +static int luaB_type (lua_State *L) { + int t = lua_type(L, 1); + luaL_argcheck(L, t != LUA_TNONE, 1, "value expected"); + lua_pushstring(L, lua_typename(L, t)); + return 1; +} + + +static int pairsmeta (lua_State *L, const char *method, int iszero, + lua_CFunction iter) { + luaL_checkany(L, 1); + if (luaL_getmetafield(L, 1, method) == LUA_TNIL) { /* no metamethod? */ + lua_pushcfunction(L, iter); /* will return generator, */ + lua_pushvalue(L, 1); /* state, */ + if (iszero) lua_pushinteger(L, 0); /* and initial value */ + else lua_pushnil(L); + } + else { + lua_pushvalue(L, 1); /* argument 'self' to metamethod */ + lua_call(L, 1, 3); /* get 3 values from metamethod */ + } + return 3; +} + + +static int luaB_next (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 2); /* create a 2nd argument if there isn't one */ + if (lua_next(L, 1)) + return 2; + else { + lua_pushnil(L); + return 1; + } +} + + +static int luaB_pairs (lua_State *L) { + return pairsmeta(L, "__pairs", 0, luaB_next); +} + + +/* +** Traversal function for 'ipairs' +*/ +static int ipairsaux (lua_State *L) { + lua_Integer i = luaL_checkinteger(L, 2) + 1; + lua_pushinteger(L, i); + return (lua_geti(L, 1, i) == LUA_TNIL) ? 1 : 2; +} + + +/* +** 'ipairs' function. Returns 'ipairsaux', given "table", 0. +** (The given "table" may not be a table.) +*/ +static int luaB_ipairs (lua_State *L) { +#if defined(LUA_COMPAT_IPAIRS) + return pairsmeta(L, "__ipairs", 1, ipairsaux); +#else + luaL_checkany(L, 1); + lua_pushcfunction(L, ipairsaux); /* iteration function */ + lua_pushvalue(L, 1); /* state */ + lua_pushinteger(L, 0); /* initial value */ + return 3; +#endif +} + + +static int load_aux (lua_State *L, int status, int envidx) { + if (status == LUA_OK) { + if (envidx != 0) { /* 'env' parameter? */ + lua_pushvalue(L, envidx); /* environment for loaded function */ + if (!lua_setupvalue(L, -2, 1)) /* set it as 1st upvalue */ + lua_pop(L, 1); /* remove 'env' if not used by previous call */ + } + return 1; + } + else { /* error (message is on top of the stack) */ + lua_pushnil(L); + lua_insert(L, -2); /* put before error message */ + return 2; /* return nil plus error message */ + } +} + + +static int luaB_loadfile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + const char *mode = luaL_optstring(L, 2, NULL); + int env = (!lua_isnone(L, 3) ? 3 : 0); /* 'env' index or 0 if no 'env' */ + int status = luaL_loadfilex(L, fname, mode); + return load_aux(L, status, env); +} + + +/* +** {====================================================== +** Generic Read function +** ======================================================= +*/ + + +/* +** reserved slot, above all arguments, to hold a copy of the returned +** string to avoid it being collected while parsed. 'load' has four +** optional arguments (chunk, source name, mode, and environment). +*/ +#define RESERVEDSLOT 5 + + +/* +** Reader for generic 'load' function: 'lua_load' uses the +** stack for internal stuff, so the reader cannot change the +** stack top. Instead, it keeps its resulting string in a +** reserved slot inside the stack. +*/ +static const char *generic_reader (lua_State *L, void *ud, size_t *size) { + (void)(ud); /* not used */ + luaL_checkstack(L, 2, "too many nested functions"); + lua_pushvalue(L, 1); /* get function */ + lua_call(L, 0, 1); /* call it */ + if (lua_isnil(L, -1)) { + lua_pop(L, 1); /* pop result */ + *size = 0; + return NULL; + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "reader function must return a string"); + lua_replace(L, RESERVEDSLOT); /* save string in reserved slot */ + return lua_tolstring(L, RESERVEDSLOT, size); +} + + +static int luaB_load (lua_State *L) { + int status; + size_t l; + const char *s = lua_tolstring(L, 1, &l); + const char *mode = luaL_optstring(L, 3, "bt"); + int env = (!lua_isnone(L, 4) ? 4 : 0); /* 'env' index or 0 if no 'env' */ + if (s != NULL) { /* loading a string? */ + const char *chunkname = luaL_optstring(L, 2, s); + status = luaL_loadbufferx(L, s, l, chunkname, mode); + } + else { /* loading from a reader function */ + const char *chunkname = luaL_optstring(L, 2, "=(load)"); + luaL_checktype(L, 1, LUA_TFUNCTION); + lua_settop(L, RESERVEDSLOT); /* create reserved slot */ + status = lua_load(L, generic_reader, NULL, chunkname, mode); + } + return load_aux(L, status, env); +} + +/* }====================================================== */ + + +static int dofilecont (lua_State *L, int d1, lua_KContext d2) { + (void)d1; (void)d2; /* only to match 'lua_Kfunction' prototype */ + return lua_gettop(L) - 1; +} + + +static int luaB_dofile (lua_State *L) { + const char *fname = luaL_optstring(L, 1, NULL); + lua_settop(L, 1); + if (luaL_loadfile(L, fname) != LUA_OK) + return lua_error(L); + lua_callk(L, 0, LUA_MULTRET, 0, dofilecont); + return dofilecont(L, 0, 0); +} + + +static int luaB_assert (lua_State *L) { + if (lua_toboolean(L, 1)) /* condition is true? */ + return lua_gettop(L); /* return all arguments */ + else { /* error */ + luaL_checkany(L, 1); /* there must be a condition */ + lua_remove(L, 1); /* remove it */ + lua_pushliteral(L, "assertion failed!"); /* default message */ + lua_settop(L, 1); /* leave only message (default if no other one) */ + return luaB_error(L); /* call 'error' */ + } +} + + +static int luaB_select (lua_State *L) { + int n = lua_gettop(L); + if (lua_type(L, 1) == LUA_TSTRING && *lua_tostring(L, 1) == '#') { + lua_pushinteger(L, n-1); + return 1; + } + else { + lua_Integer i = luaL_checkinteger(L, 1); + if (i < 0) i = n + i; + else if (i > n) i = n; + luaL_argcheck(L, 1 <= i, 1, "index out of range"); + return n - (int)i; + } +} + + +/* +** Continuation function for 'pcall' and 'xpcall'. Both functions +** already pushed a 'true' before doing the call, so in case of success +** 'finishpcall' only has to return everything in the stack minus +** 'extra' values (where 'extra' is exactly the number of items to be +** ignored). +*/ +static int finishpcall (lua_State *L, int status, lua_KContext extra) { + if (status != LUA_OK && status != LUA_YIELD) { /* error? */ + lua_pushboolean(L, 0); /* first result (false) */ + lua_pushvalue(L, -2); /* error message */ + return 2; /* return false, msg */ + } + else + return lua_gettop(L) - (int)extra; /* return all results */ +} + + +static int luaB_pcall (lua_State *L) { + int status; + luaL_checkany(L, 1); + lua_pushboolean(L, 1); /* first result if no errors */ + lua_insert(L, 1); /* put it in place */ + status = lua_pcallk(L, lua_gettop(L) - 2, LUA_MULTRET, 0, 0, finishpcall); + return finishpcall(L, status, 0); +} + + +/* +** Do a protected call with error handling. After 'lua_rotate', the +** stack will have ; so, the function passes +** 2 to 'finishpcall' to skip the 2 first values when returning results. +*/ +static int luaB_xpcall (lua_State *L) { + int status; + int n = lua_gettop(L); + luaL_checktype(L, 2, LUA_TFUNCTION); /* check error function */ + lua_pushboolean(L, 1); /* first result */ + lua_pushvalue(L, 1); /* function */ + lua_rotate(L, 3, 2); /* move them below function's arguments */ + status = lua_pcallk(L, n - 2, LUA_MULTRET, 2, 2, finishpcall); + return finishpcall(L, status, 2); +} + + +static int luaB_tostring (lua_State *L) { + luaL_checkany(L, 1); + luaL_tolstring(L, 1, NULL); + return 1; +} + + +static const luaL_Reg base_funcs[] = { + {"assert", luaB_assert}, + {"collectgarbage", luaB_collectgarbage}, + {"dofile", luaB_dofile}, + {"error", luaB_error}, + {"getmetatable", luaB_getmetatable}, + {"ipairs", luaB_ipairs}, + {"loadfile", luaB_loadfile}, + {"load", luaB_load}, +#if defined(LUA_COMPAT_LOADSTRING) + {"loadstring", luaB_load}, +#endif + {"next", luaB_next}, + {"pairs", luaB_pairs}, + {"pcall", luaB_pcall}, + {"print", luaB_print}, + {"rawequal", luaB_rawequal}, + {"rawlen", luaB_rawlen}, + {"rawget", luaB_rawget}, + {"rawset", luaB_rawset}, + {"select", luaB_select}, + {"setmetatable", luaB_setmetatable}, + {"tonumber", luaB_tonumber}, + {"tostring", luaB_tostring}, + {"type", luaB_type}, + {"xpcall", luaB_xpcall}, + /* placeholders */ + {"_G", NULL}, + {"_VERSION", NULL}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_base (lua_State *L) { + /* open lib into global table */ + lua_pushglobaltable(L); + luaL_setfuncs(L, base_funcs, 0); + /* set global _G */ + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_G"); + /* set global _VERSION */ + lua_pushliteral(L, LUA_VERSION); + lua_setfield(L, -2, "_VERSION"); + return 1; +} + diff --git a/src/lua/lbitlib.c b/src/lua/lbitlib.c new file mode 100644 index 000000000000..4786c0d48302 --- /dev/null +++ b/src/lua/lbitlib.c @@ -0,0 +1,233 @@ +/* +** $Id: lbitlib.c,v 1.30.1.1 2017/04/19 17:20:42 roberto Exp $ +** Standard library for bitwise operations +** See Copyright Notice in lua.h +*/ + +#define lbitlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#if defined(LUA_COMPAT_BITLIB) /* { */ + + +#define pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define checkunsigned(L,i) ((lua_Unsigned)luaL_checkinteger(L,i)) + + +/* number of bits to consider in a number */ +#if !defined(LUA_NBITS) +#define LUA_NBITS 32 +#endif + + +/* +** a lua_Unsigned with its first LUA_NBITS bits equal to 1. (Shift must +** be made in two parts to avoid problems when LUA_NBITS is equal to the +** number of bits in a lua_Unsigned.) +*/ +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) + + +/* macro to trim extra bits */ +#define trim(x) ((x) & ALLONES) + + +/* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) + + + +static lua_Unsigned andaux (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = ~(lua_Unsigned)0; + for (i = 1; i <= n; i++) + r &= checkunsigned(L, i); + return trim(r); +} + + +static int b_and (lua_State *L) { + lua_Unsigned r = andaux(L); + pushunsigned(L, r); + return 1; +} + + +static int b_test (lua_State *L) { + lua_Unsigned r = andaux(L); + lua_pushboolean(L, r != 0); + return 1; +} + + +static int b_or (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = 0; + for (i = 1; i <= n; i++) + r |= checkunsigned(L, i); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_xor (lua_State *L) { + int i, n = lua_gettop(L); + lua_Unsigned r = 0; + for (i = 1; i <= n; i++) + r ^= checkunsigned(L, i); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_not (lua_State *L) { + lua_Unsigned r = ~checkunsigned(L, 1); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_shift (lua_State *L, lua_Unsigned r, lua_Integer i) { + if (i < 0) { /* shift right? */ + i = -i; + r = trim(r); + if (i >= LUA_NBITS) r = 0; + else r >>= i; + } + else { /* shift left */ + if (i >= LUA_NBITS) r = 0; + else r <<= i; + r = trim(r); + } + pushunsigned(L, r); + return 1; +} + + +static int b_lshift (lua_State *L) { + return b_shift(L, checkunsigned(L, 1), luaL_checkinteger(L, 2)); +} + + +static int b_rshift (lua_State *L) { + return b_shift(L, checkunsigned(L, 1), -luaL_checkinteger(L, 2)); +} + + +static int b_arshift (lua_State *L) { + lua_Unsigned r = checkunsigned(L, 1); + lua_Integer i = luaL_checkinteger(L, 2); + if (i < 0 || !(r & ((lua_Unsigned)1 << (LUA_NBITS - 1)))) + return b_shift(L, r, -i); + else { /* arithmetic shift for 'negative' number */ + if (i >= LUA_NBITS) r = ALLONES; + else + r = trim((r >> i) | ~(trim(~(lua_Unsigned)0) >> i)); /* add signal bit */ + pushunsigned(L, r); + return 1; + } +} + + +static int b_rot (lua_State *L, lua_Integer d) { + lua_Unsigned r = checkunsigned(L, 1); + int i = d & (LUA_NBITS - 1); /* i = d % NBITS */ + r = trim(r); + if (i != 0) /* avoid undefined shift of LUA_NBITS when i == 0 */ + r = (r << i) | (r >> (LUA_NBITS - i)); + pushunsigned(L, trim(r)); + return 1; +} + + +static int b_lrot (lua_State *L) { + return b_rot(L, luaL_checkinteger(L, 2)); +} + + +static int b_rrot (lua_State *L) { + return b_rot(L, -luaL_checkinteger(L, 2)); +} + + +/* +** get field and width arguments for field-manipulation functions, +** checking whether they are valid. +** ('luaL_error' called without 'return' to avoid later warnings about +** 'width' being used uninitialized.) +*/ +static int fieldargs (lua_State *L, int farg, int *width) { + lua_Integer f = luaL_checkinteger(L, farg); + lua_Integer w = luaL_optinteger(L, farg + 1, 1); + luaL_argcheck(L, 0 <= f, farg, "field cannot be negative"); + luaL_argcheck(L, 0 < w, farg + 1, "width must be positive"); + if (f + w > LUA_NBITS) + luaL_error(L, "trying to access non-existent bits"); + *width = (int)w; + return (int)f; +} + + +static int b_extract (lua_State *L) { + int w; + lua_Unsigned r = trim(checkunsigned(L, 1)); + int f = fieldargs(L, 2, &w); + r = (r >> f) & mask(w); + pushunsigned(L, r); + return 1; +} + + +static int b_replace (lua_State *L) { + int w; + lua_Unsigned r = trim(checkunsigned(L, 1)); + lua_Unsigned v = trim(checkunsigned(L, 2)); + int f = fieldargs(L, 3, &w); + lua_Unsigned m = mask(w); + r = (r & ~(m << f)) | ((v & m) << f); + pushunsigned(L, r); + return 1; +} + + +static const luaL_Reg bitlib[] = { + {"arshift", b_arshift}, + {"band", b_and}, + {"bnot", b_not}, + {"bor", b_or}, + {"bxor", b_xor}, + {"btest", b_test}, + {"extract", b_extract}, + {"lrotate", b_lrot}, + {"lshift", b_lshift}, + {"replace", b_replace}, + {"rrotate", b_rrot}, + {"rshift", b_rshift}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + luaL_newlib(L, bitlib); + return 1; +} + + +#else /* }{ */ + + +LUAMOD_API int luaopen_bit32 (lua_State *L) { + return luaL_error(L, "library 'bit32' has been deprecated"); +} + +#endif /* } */ diff --git a/src/lua/lcode.c b/src/lua/lcode.c new file mode 100644 index 000000000000..dc7271d61419 --- /dev/null +++ b/src/lua/lcode.c @@ -0,0 +1,1203 @@ +/* +** $Id: lcode.c,v 2.112.1.1 2017/04/19 17:20:42 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#define lcode_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +/* Maximum number of registers in a Lua function (must fit in 8 bits) */ +#define MAXREGS 255 + + +#define hasjumps(e) ((e)->t != (e)->f) + + +/* +** If expression is a numeric constant, fills 'v' with its value +** and returns 1. Otherwise, returns 0. +*/ +static int tonumeral(const expdesc *e, TValue *v) { + if (hasjumps(e)) + return 0; /* not a numeral */ + switch (e->k) { + case VKINT: + if (v) setivalue(v, e->u.ival); + return 1; + case VKFLT: + if (v) setfltvalue(v, e->u.nval); + return 1; + default: return 0; + } +} + + +/* +** Create a OP_LOADNIL instruction, but try to optimize: if the previous +** instruction is also OP_LOADNIL and ranges are compatible, adjust +** range of previous instruction instead of emitting a new one. (For +** instance, 'local a; local b' will generate a single opcode.) +*/ +void luaK_nil (FuncState *fs, int from, int n) { + Instruction *previous; + int l = from + n - 1; /* last register to set nil */ + if (fs->pc > fs->lasttarget) { /* no jumps to current position? */ + previous = &fs->f->code[fs->pc-1]; + if (GET_OPCODE(*previous) == OP_LOADNIL) { /* previous is LOADNIL? */ + int pfrom = GETARG_A(*previous); /* get previous range */ + int pl = pfrom + GETARG_B(*previous); + if ((pfrom <= from && from <= pl + 1) || + (from <= pfrom && pfrom <= l + 1)) { /* can connect both? */ + if (pfrom < from) from = pfrom; /* from = min(from, pfrom) */ + if (pl > l) l = pl; /* l = max(l, pl) */ + SETARG_A(*previous, from); + SETARG_B(*previous, l - from); + return; + } + } /* else go through */ + } + luaK_codeABC(fs, OP_LOADNIL, from, n - 1, 0); /* else no optimization */ +} + + +/* +** Gets the destination address of a jump instruction. Used to traverse +** a list of jumps. +*/ +static int getjump (FuncState *fs, int pc) { + int offset = GETARG_sBx(fs->f->code[pc]); + if (offset == NO_JUMP) /* point to itself represents end of list */ + return NO_JUMP; /* end of list */ + else + return (pc+1)+offset; /* turn offset into absolute position */ +} + + +/* +** Fix jump instruction at position 'pc' to jump to 'dest'. +** (Jump addresses are relative in Lua) +*/ +static void fixjump (FuncState *fs, int pc, int dest) { + Instruction *jmp = &fs->f->code[pc]; + int offset = dest - (pc + 1); + lua_assert(dest != NO_JUMP); + if (abs(offset) > MAXARG_sBx) + luaX_syntaxerror(fs->ls, "control structure too long"); + SETARG_sBx(*jmp, offset); +} + + +/* +** Concatenate jump-list 'l2' into jump-list 'l1' +*/ +void luaK_concat (FuncState *fs, int *l1, int l2) { + if (l2 == NO_JUMP) return; /* nothing to concatenate? */ + else if (*l1 == NO_JUMP) /* no original list? */ + *l1 = l2; /* 'l1' points to 'l2' */ + else { + int list = *l1; + int next; + while ((next = getjump(fs, list)) != NO_JUMP) /* find last element */ + list = next; + fixjump(fs, list, l2); /* last element links to 'l2' */ + } +} + + +/* +** Create a jump instruction and return its position, so its destination +** can be fixed later (with 'fixjump'). If there are jumps to +** this position (kept in 'jpc'), link them all together so that +** 'patchlistaux' will fix all them directly to the final destination. +*/ +int luaK_jump (FuncState *fs) { + int jpc = fs->jpc; /* save list of jumps to here */ + int j; + fs->jpc = NO_JUMP; /* no more jumps to here */ + j = luaK_codeAsBx(fs, OP_JMP, 0, NO_JUMP); + luaK_concat(fs, &j, jpc); /* keep them on hold */ + return j; +} + + +/* +** Code a 'return' instruction +*/ +void luaK_ret (FuncState *fs, int first, int nret) { + luaK_codeABC(fs, OP_RETURN, first, nret+1, 0); +} + + +/* +** Code a "conditional jump", that is, a test or comparison opcode +** followed by a jump. Return jump position. +*/ +static int condjump (FuncState *fs, OpCode op, int A, int B, int C) { + luaK_codeABC(fs, op, A, B, C); + return luaK_jump(fs); +} + + +/* +** returns current 'pc' and marks it as a jump target (to avoid wrong +** optimizations with consecutive instructions not in the same basic block). +*/ +int luaK_getlabel (FuncState *fs) { + fs->lasttarget = fs->pc; + return fs->pc; +} + + +/* +** Returns the position of the instruction "controlling" a given +** jump (that is, its condition), or the jump itself if it is +** unconditional. +*/ +static Instruction *getjumpcontrol (FuncState *fs, int pc) { + Instruction *pi = &fs->f->code[pc]; + if (pc >= 1 && testTMode(GET_OPCODE(*(pi-1)))) + return pi-1; + else + return pi; +} + + +/* +** Patch destination register for a TESTSET instruction. +** If instruction in position 'node' is not a TESTSET, return 0 ("fails"). +** Otherwise, if 'reg' is not 'NO_REG', set it as the destination +** register. Otherwise, change instruction to a simple 'TEST' (produces +** no register value) +*/ +static int patchtestreg (FuncState *fs, int node, int reg) { + Instruction *i = getjumpcontrol(fs, node); + if (GET_OPCODE(*i) != OP_TESTSET) + return 0; /* cannot patch other instructions */ + if (reg != NO_REG && reg != GETARG_B(*i)) + SETARG_A(*i, reg); + else { + /* no register to put value or register already has the value; + change instruction to simple test */ + *i = CREATE_ABC(OP_TEST, GETARG_B(*i), 0, GETARG_C(*i)); + } + return 1; +} + + +/* +** Traverse a list of tests ensuring no one produces a value +*/ +static void removevalues (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) + patchtestreg(fs, list, NO_REG); +} + + +/* +** Traverse a list of tests, patching their destination address and +** registers: tests producing values jump to 'vtarget' (and put their +** values in 'reg'), other tests jump to 'dtarget'. +*/ +static void patchlistaux (FuncState *fs, int list, int vtarget, int reg, + int dtarget) { + while (list != NO_JUMP) { + int next = getjump(fs, list); + if (patchtestreg(fs, list, reg)) + fixjump(fs, list, vtarget); + else + fixjump(fs, list, dtarget); /* jump to default target */ + list = next; + } +} + + +/* +** Ensure all pending jumps to current position are fixed (jumping +** to current position with no values) and reset list of pending +** jumps +*/ +static void dischargejpc (FuncState *fs) { + patchlistaux(fs, fs->jpc, fs->pc, NO_REG, fs->pc); + fs->jpc = NO_JUMP; +} + + +/* +** Add elements in 'list' to list of pending jumps to "here" +** (current position) +*/ +void luaK_patchtohere (FuncState *fs, int list) { + luaK_getlabel(fs); /* mark "here" as a jump target */ + luaK_concat(fs, &fs->jpc, list); +} + + +/* +** Path all jumps in 'list' to jump to 'target'. +** (The assert means that we cannot fix a jump to a forward address +** because we only know addresses once code is generated.) +*/ +void luaK_patchlist (FuncState *fs, int list, int target) { + if (target == fs->pc) /* 'target' is current position? */ + luaK_patchtohere(fs, list); /* add list to pending jumps */ + else { + lua_assert(target < fs->pc); + patchlistaux(fs, list, target, NO_REG, target); + } +} + + +/* +** Path all jumps in 'list' to close upvalues up to given 'level' +** (The assertion checks that jumps either were closing nothing +** or were closing higher levels, from inner blocks.) +*/ +void luaK_patchclose (FuncState *fs, int list, int level) { + level++; /* argument is +1 to reserve 0 as non-op */ + for (; list != NO_JUMP; list = getjump(fs, list)) { + lua_assert(GET_OPCODE(fs->f->code[list]) == OP_JMP && + (GETARG_A(fs->f->code[list]) == 0 || + GETARG_A(fs->f->code[list]) >= level)); + SETARG_A(fs->f->code[list], level); + } +} + + +/* +** Emit instruction 'i', checking for array sizes and saving also its +** line information. Return 'i' position. +*/ +static int luaK_code (FuncState *fs, Instruction i) { + Proto *f = fs->f; + dischargejpc(fs); /* 'pc' will change */ + /* put new instruction in code array */ + luaM_growvector(fs->ls->L, f->code, fs->pc, f->sizecode, Instruction, + MAX_INT, "opcodes"); + f->code[fs->pc] = i; + /* save corresponding line information */ + luaM_growvector(fs->ls->L, f->lineinfo, fs->pc, f->sizelineinfo, int, + MAX_INT, "opcodes"); + f->lineinfo[fs->pc] = fs->ls->lastline; + return fs->pc++; +} + + +/* +** Format and emit an 'iABC' instruction. (Assertions check consistency +** of parameters versus opcode.) +*/ +int luaK_codeABC (FuncState *fs, OpCode o, int a, int b, int c) { + lua_assert(getOpMode(o) == iABC); + lua_assert(getBMode(o) != OpArgN || b == 0); + lua_assert(getCMode(o) != OpArgN || c == 0); + lua_assert(a <= MAXARG_A && b <= MAXARG_B && c <= MAXARG_C); + return luaK_code(fs, CREATE_ABC(o, a, b, c)); +} + + +/* +** Format and emit an 'iABx' instruction. +*/ +int luaK_codeABx (FuncState *fs, OpCode o, int a, unsigned int bc) { + lua_assert(getOpMode(o) == iABx || getOpMode(o) == iAsBx); + lua_assert(getCMode(o) == OpArgN); + lua_assert(a <= MAXARG_A && bc <= MAXARG_Bx); + return luaK_code(fs, CREATE_ABx(o, a, bc)); +} + + +/* +** Emit an "extra argument" instruction (format 'iAx') +*/ +static int codeextraarg (FuncState *fs, int a) { + lua_assert(a <= MAXARG_Ax); + return luaK_code(fs, CREATE_Ax(OP_EXTRAARG, a)); +} + + +/* +** Emit a "load constant" instruction, using either 'OP_LOADK' +** (if constant index 'k' fits in 18 bits) or an 'OP_LOADKX' +** instruction with "extra argument". +*/ +int luaK_codek (FuncState *fs, int reg, int k) { + if (k <= MAXARG_Bx) + return luaK_codeABx(fs, OP_LOADK, reg, k); + else { + int p = luaK_codeABx(fs, OP_LOADKX, reg, 0); + codeextraarg(fs, k); + return p; + } +} + + +/* +** Check register-stack level, keeping track of its maximum size +** in field 'maxstacksize' +*/ +void luaK_checkstack (FuncState *fs, int n) { + int newstack = fs->freereg + n; + if (newstack > fs->f->maxstacksize) { + if (newstack >= MAXREGS) + luaX_syntaxerror(fs->ls, + "function or expression needs too many registers"); + fs->f->maxstacksize = cast_byte(newstack); + } +} + + +/* +** Reserve 'n' registers in register stack +*/ +void luaK_reserveregs (FuncState *fs, int n) { + luaK_checkstack(fs, n); + fs->freereg += n; +} + + +/* +** Free register 'reg', if it is neither a constant index nor +** a local variable. +) +*/ +static void freereg (FuncState *fs, int reg) { + if (!ISK(reg) && reg >= fs->nactvar) { + fs->freereg--; + lua_assert(reg == fs->freereg); + } +} + + +/* +** Free register used by expression 'e' (if any) +*/ +static void freeexp (FuncState *fs, expdesc *e) { + if (e->k == VNONRELOC) + freereg(fs, e->u.info); +} + + +/* +** Free registers used by expressions 'e1' and 'e2' (if any) in proper +** order. +*/ +static void freeexps (FuncState *fs, expdesc *e1, expdesc *e2) { + int r1 = (e1->k == VNONRELOC) ? e1->u.info : -1; + int r2 = (e2->k == VNONRELOC) ? e2->u.info : -1; + if (r1 > r2) { + freereg(fs, r1); + freereg(fs, r2); + } + else { + freereg(fs, r2); + freereg(fs, r1); + } +} + + +/* +** Add constant 'v' to prototype's list of constants (field 'k'). +** Use scanner's table to cache position of constants in constant list +** and try to reuse constants. Because some values should not be used +** as keys (nil cannot be a key, integer keys can collapse with float +** keys), the caller must provide a useful 'key' for indexing the cache. +*/ +static int addk (FuncState *fs, TValue *key, TValue *v) { + lua_State *L = fs->ls->L; + Proto *f = fs->f; + TValue *idx = luaH_set(L, fs->ls->h, key); /* index scanner table */ + int k, oldsize; + if (ttisinteger(idx)) { /* is there an index there? */ + k = cast_int(ivalue(idx)); + /* correct value? (warning: must distinguish floats from integers!) */ + if (k < fs->nk && ttype(&f->k[k]) == ttype(v) && + luaV_rawequalobj(&f->k[k], v)) + return k; /* reuse index */ + } + /* constant not found; create a new entry */ + oldsize = f->sizek; + k = fs->nk; + /* numerical value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setivalue(idx, k); + luaM_growvector(L, f->k, k, f->sizek, TValue, MAXARG_Ax, "constants"); + while (oldsize < f->sizek) setnilvalue(&f->k[oldsize++]); + setobj(L, &f->k[k], v); + fs->nk++; + luaC_barrier(L, f, v); + return k; +} + + +/* +** Add a string to list of constants and return its index. +*/ +int luaK_stringK (FuncState *fs, TString *s) { + TValue o; + setsvalue(fs->ls->L, &o, s); + return addk(fs, &o, &o); /* use string itself as key */ +} + + +/* +** Add an integer to list of constants and return its index. +** Integers use userdata as keys to avoid collision with floats with +** same value; conversion to 'void*' is used only for hashing, so there +** are no "precision" problems. +*/ +int luaK_intK (FuncState *fs, lua_Integer n) { + TValue k, o; + setpvalue(&k, cast(void*, cast(size_t, n))); + setivalue(&o, n); + return addk(fs, &k, &o); +} + +/* +** Add a float to list of constants and return its index. +*/ +static int luaK_numberK (FuncState *fs, lua_Number r) { + TValue o; + setfltvalue(&o, r); + return addk(fs, &o, &o); /* use number itself as key */ +} + + +/* +** Add a boolean to list of constants and return its index. +*/ +static int boolK (FuncState *fs, int b) { + TValue o; + setbvalue(&o, b); + return addk(fs, &o, &o); /* use boolean itself as key */ +} + + +/* +** Add nil to list of constants and return its index. +*/ +static int nilK (FuncState *fs) { + TValue k, v; + setnilvalue(&v); + /* cannot use nil as key; instead use table itself to represent nil */ + sethvalue(fs->ls->L, &k, fs->ls->h); + return addk(fs, &k, &v); +} + + +/* +** Fix an expression to return the number of results 'nresults'. +** Either 'e' is a multi-ret expression (function call or vararg) +** or 'nresults' is LUA_MULTRET (as any expression can satisfy that). +*/ +void luaK_setreturns (FuncState *fs, expdesc *e, int nresults) { + if (e->k == VCALL) { /* expression is an open function call? */ + SETARG_C(getinstruction(fs, e), nresults + 1); + } + else if (e->k == VVARARG) { + Instruction *pc = &getinstruction(fs, e); + SETARG_B(*pc, nresults + 1); + SETARG_A(*pc, fs->freereg); + luaK_reserveregs(fs, 1); + } + else lua_assert(nresults == LUA_MULTRET); +} + + +/* +** Fix an expression to return one result. +** If expression is not a multi-ret expression (function call or +** vararg), it already returns one result, so nothing needs to be done. +** Function calls become VNONRELOC expressions (as its result comes +** fixed in the base register of the call), while vararg expressions +** become VRELOCABLE (as OP_VARARG puts its results where it wants). +** (Calls are created returning one result, so that does not need +** to be fixed.) +*/ +void luaK_setoneret (FuncState *fs, expdesc *e) { + if (e->k == VCALL) { /* expression is an open function call? */ + /* already returns 1 value */ + lua_assert(GETARG_C(getinstruction(fs, e)) == 2); + e->k = VNONRELOC; /* result has fixed position */ + e->u.info = GETARG_A(getinstruction(fs, e)); + } + else if (e->k == VVARARG) { + SETARG_B(getinstruction(fs, e), 2); + e->k = VRELOCABLE; /* can relocate its simple result */ + } +} + + +/* +** Ensure that expression 'e' is not a variable. +*/ +void luaK_dischargevars (FuncState *fs, expdesc *e) { + switch (e->k) { + case VLOCAL: { /* already in a register */ + e->k = VNONRELOC; /* becomes a non-relocatable value */ + break; + } + case VUPVAL: { /* move value to some (pending) register */ + e->u.info = luaK_codeABC(fs, OP_GETUPVAL, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + case VINDEXED: { + OpCode op; + freereg(fs, e->u.ind.idx); + if (e->u.ind.vt == VLOCAL) { /* is 't' in a register? */ + freereg(fs, e->u.ind.t); + op = OP_GETTABLE; + } + else { + lua_assert(e->u.ind.vt == VUPVAL); + op = OP_GETTABUP; /* 't' is in an upvalue */ + } + e->u.info = luaK_codeABC(fs, op, 0, e->u.ind.t, e->u.ind.idx); + e->k = VRELOCABLE; + break; + } + case VVARARG: case VCALL: { + luaK_setoneret(fs, e); + break; + } + default: break; /* there is one value available (somewhere) */ + } +} + + +/* +** Ensures expression value is in register 'reg' (and therefore +** 'e' will become a non-relocatable expression). +*/ +static void discharge2reg (FuncState *fs, expdesc *e, int reg) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: { + luaK_nil(fs, reg, 1); + break; + } + case VFALSE: case VTRUE: { + luaK_codeABC(fs, OP_LOADBOOL, reg, e->k == VTRUE, 0); + break; + } + case VK: { + luaK_codek(fs, reg, e->u.info); + break; + } + case VKFLT: { + luaK_codek(fs, reg, luaK_numberK(fs, e->u.nval)); + break; + } + case VKINT: { + luaK_codek(fs, reg, luaK_intK(fs, e->u.ival)); + break; + } + case VRELOCABLE: { + Instruction *pc = &getinstruction(fs, e); + SETARG_A(*pc, reg); /* instruction will put result in 'reg' */ + break; + } + case VNONRELOC: { + if (reg != e->u.info) + luaK_codeABC(fs, OP_MOVE, reg, e->u.info, 0); + break; + } + default: { + lua_assert(e->k == VJMP); + return; /* nothing to do... */ + } + } + e->u.info = reg; + e->k = VNONRELOC; +} + + +/* +** Ensures expression value is in any register. +*/ +static void discharge2anyreg (FuncState *fs, expdesc *e) { + if (e->k != VNONRELOC) { /* no fixed register yet? */ + luaK_reserveregs(fs, 1); /* get a register */ + discharge2reg(fs, e, fs->freereg-1); /* put value there */ + } +} + + +static int code_loadbool (FuncState *fs, int A, int b, int jump) { + luaK_getlabel(fs); /* those instructions may be jump targets */ + return luaK_codeABC(fs, OP_LOADBOOL, A, b, jump); +} + + +/* +** check whether list has any jump that do not produce a value +** or produce an inverted value +*/ +static int need_value (FuncState *fs, int list) { + for (; list != NO_JUMP; list = getjump(fs, list)) { + Instruction i = *getjumpcontrol(fs, list); + if (GET_OPCODE(i) != OP_TESTSET) return 1; + } + return 0; /* not found */ +} + + +/* +** Ensures final expression result (including results from its jump +** lists) is in register 'reg'. +** If expression has jumps, need to patch these jumps either to +** its final position or to "load" instructions (for those tests +** that do not produce values). +*/ +static void exp2reg (FuncState *fs, expdesc *e, int reg) { + discharge2reg(fs, e, reg); + if (e->k == VJMP) /* expression itself is a test? */ + luaK_concat(fs, &e->t, e->u.info); /* put this jump in 't' list */ + if (hasjumps(e)) { + int final; /* position after whole expression */ + int p_f = NO_JUMP; /* position of an eventual LOAD false */ + int p_t = NO_JUMP; /* position of an eventual LOAD true */ + if (need_value(fs, e->t) || need_value(fs, e->f)) { + int fj = (e->k == VJMP) ? NO_JUMP : luaK_jump(fs); + p_f = code_loadbool(fs, reg, 0, 1); + p_t = code_loadbool(fs, reg, 1, 0); + luaK_patchtohere(fs, fj); + } + final = luaK_getlabel(fs); + patchlistaux(fs, e->f, final, reg, p_f); + patchlistaux(fs, e->t, final, reg, p_t); + } + e->f = e->t = NO_JUMP; + e->u.info = reg; + e->k = VNONRELOC; +} + + +/* +** Ensures final expression result (including results from its jump +** lists) is in next available register. +*/ +void luaK_exp2nextreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + freeexp(fs, e); + luaK_reserveregs(fs, 1); + exp2reg(fs, e, fs->freereg - 1); +} + + +/* +** Ensures final expression result (including results from its jump +** lists) is in some (any) register and return that register. +*/ +int luaK_exp2anyreg (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + if (e->k == VNONRELOC) { /* expression already has a register? */ + if (!hasjumps(e)) /* no jumps? */ + return e->u.info; /* result is already in a register */ + if (e->u.info >= fs->nactvar) { /* reg. is not a local? */ + exp2reg(fs, e, e->u.info); /* put final result in it */ + return e->u.info; + } + } + luaK_exp2nextreg(fs, e); /* otherwise, use next available register */ + return e->u.info; +} + + +/* +** Ensures final expression result is either in a register or in an +** upvalue. +*/ +void luaK_exp2anyregup (FuncState *fs, expdesc *e) { + if (e->k != VUPVAL || hasjumps(e)) + luaK_exp2anyreg(fs, e); +} + + +/* +** Ensures final expression result is either in a register or it is +** a constant. +*/ +void luaK_exp2val (FuncState *fs, expdesc *e) { + if (hasjumps(e)) + luaK_exp2anyreg(fs, e); + else + luaK_dischargevars(fs, e); +} + + +/* +** Ensures final expression result is in a valid R/K index +** (that is, it is either in a register or in 'k' with an index +** in the range of R/K indices). +** Returns R/K index. +*/ +int luaK_exp2RK (FuncState *fs, expdesc *e) { + luaK_exp2val(fs, e); + switch (e->k) { /* move constants to 'k' */ + case VTRUE: e->u.info = boolK(fs, 1); goto vk; + case VFALSE: e->u.info = boolK(fs, 0); goto vk; + case VNIL: e->u.info = nilK(fs); goto vk; + case VKINT: e->u.info = luaK_intK(fs, e->u.ival); goto vk; + case VKFLT: e->u.info = luaK_numberK(fs, e->u.nval); goto vk; + case VK: + vk: + e->k = VK; + if (e->u.info <= MAXINDEXRK) /* constant fits in 'argC'? */ + return RKASK(e->u.info); + else break; + default: break; + } + /* not a constant in the right range: put it in a register */ + return luaK_exp2anyreg(fs, e); +} + + +/* +** Generate code to store result of expression 'ex' into variable 'var'. +*/ +void luaK_storevar (FuncState *fs, expdesc *var, expdesc *ex) { + switch (var->k) { + case VLOCAL: { + freeexp(fs, ex); + exp2reg(fs, ex, var->u.info); /* compute 'ex' into proper place */ + return; + } + case VUPVAL: { + int e = luaK_exp2anyreg(fs, ex); + luaK_codeABC(fs, OP_SETUPVAL, e, var->u.info, 0); + break; + } + case VINDEXED: { + OpCode op = (var->u.ind.vt == VLOCAL) ? OP_SETTABLE : OP_SETTABUP; + int e = luaK_exp2RK(fs, ex); + luaK_codeABC(fs, op, var->u.ind.t, var->u.ind.idx, e); + break; + } + default: lua_assert(0); /* invalid var kind to store */ + } + freeexp(fs, ex); +} + + +/* +** Emit SELF instruction (convert expression 'e' into 'e:key(e,'). +*/ +void luaK_self (FuncState *fs, expdesc *e, expdesc *key) { + int ereg; + luaK_exp2anyreg(fs, e); + ereg = e->u.info; /* register where 'e' was placed */ + freeexp(fs, e); + e->u.info = fs->freereg; /* base register for op_self */ + e->k = VNONRELOC; /* self expression has a fixed register */ + luaK_reserveregs(fs, 2); /* function and 'self' produced by op_self */ + luaK_codeABC(fs, OP_SELF, e->u.info, ereg, luaK_exp2RK(fs, key)); + freeexp(fs, key); +} + + +/* +** Negate condition 'e' (where 'e' is a comparison). +*/ +static void negatecondition (FuncState *fs, expdesc *e) { + Instruction *pc = getjumpcontrol(fs, e->u.info); + lua_assert(testTMode(GET_OPCODE(*pc)) && GET_OPCODE(*pc) != OP_TESTSET && + GET_OPCODE(*pc) != OP_TEST); + SETARG_A(*pc, !(GETARG_A(*pc))); +} + + +/* +** Emit instruction to jump if 'e' is 'cond' (that is, if 'cond' +** is true, code will jump if 'e' is true.) Return jump position. +** Optimize when 'e' is 'not' something, inverting the condition +** and removing the 'not'. +*/ +static int jumponcond (FuncState *fs, expdesc *e, int cond) { + if (e->k == VRELOCABLE) { + Instruction ie = getinstruction(fs, e); + if (GET_OPCODE(ie) == OP_NOT) { + fs->pc--; /* remove previous OP_NOT */ + return condjump(fs, OP_TEST, GETARG_B(ie), 0, !cond); + } + /* else go through */ + } + discharge2anyreg(fs, e); + freeexp(fs, e); + return condjump(fs, OP_TESTSET, NO_REG, e->u.info, cond); +} + + +/* +** Emit code to go through if 'e' is true, jump otherwise. +*/ +void luaK_goiftrue (FuncState *fs, expdesc *e) { + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { /* condition? */ + negatecondition(fs, e); /* jump when it is false */ + pc = e->u.info; /* save jump position */ + break; + } + case VK: case VKFLT: case VKINT: case VTRUE: { + pc = NO_JUMP; /* always true; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 0); /* jump when false */ + break; + } + } + luaK_concat(fs, &e->f, pc); /* insert new jump in false list */ + luaK_patchtohere(fs, e->t); /* true list jumps to here (to go through) */ + e->t = NO_JUMP; +} + + +/* +** Emit code to go through if 'e' is false, jump otherwise. +*/ +void luaK_goiffalse (FuncState *fs, expdesc *e) { + int pc; /* pc of new jump */ + luaK_dischargevars(fs, e); + switch (e->k) { + case VJMP: { + pc = e->u.info; /* already jump if true */ + break; + } + case VNIL: case VFALSE: { + pc = NO_JUMP; /* always false; do nothing */ + break; + } + default: { + pc = jumponcond(fs, e, 1); /* jump if true */ + break; + } + } + luaK_concat(fs, &e->t, pc); /* insert new jump in 't' list */ + luaK_patchtohere(fs, e->f); /* false list jumps to here (to go through) */ + e->f = NO_JUMP; +} + + +/* +** Code 'not e', doing constant folding. +*/ +static void codenot (FuncState *fs, expdesc *e) { + luaK_dischargevars(fs, e); + switch (e->k) { + case VNIL: case VFALSE: { + e->k = VTRUE; /* true == not nil == not false */ + break; + } + case VK: case VKFLT: case VKINT: case VTRUE: { + e->k = VFALSE; /* false == not "x" == not 0.5 == not 1 == not true */ + break; + } + case VJMP: { + negatecondition(fs, e); + break; + } + case VRELOCABLE: + case VNONRELOC: { + discharge2anyreg(fs, e); + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, OP_NOT, 0, e->u.info, 0); + e->k = VRELOCABLE; + break; + } + default: lua_assert(0); /* cannot happen */ + } + /* interchange true and false lists */ + { int temp = e->f; e->f = e->t; e->t = temp; } + removevalues(fs, e->f); /* values are useless when negated */ + removevalues(fs, e->t); +} + + +/* +** Create expression 't[k]'. 't' must have its final result already in a +** register or upvalue. +*/ +void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k) { + lua_assert(!hasjumps(t) && (vkisinreg(t->k) || t->k == VUPVAL)); + t->u.ind.t = t->u.info; /* register or upvalue index */ + t->u.ind.idx = luaK_exp2RK(fs, k); /* R/K index for key */ + t->u.ind.vt = (t->k == VUPVAL) ? VUPVAL : VLOCAL; + t->k = VINDEXED; +} + + +/* +** Return false if folding can raise an error. +** Bitwise operations need operands convertible to integers; division +** operations cannot have 0 as divisor. +*/ +static int validop (int op, TValue *v1, TValue *v2) { + switch (op) { + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: case LUA_OPBNOT: { /* conversion errors */ + lua_Integer i; + return (tointeger(v1, &i) && tointeger(v2, &i)); + } + case LUA_OPDIV: case LUA_OPIDIV: case LUA_OPMOD: /* division by 0 */ + return (nvalue(v2) != 0); + default: return 1; /* everything else is valid */ + } +} + + +/* +** Try to "constant-fold" an operation; return 1 iff successful. +** (In this case, 'e1' has the final result.) +*/ +static int constfolding (FuncState *fs, int op, expdesc *e1, + const expdesc *e2) { + TValue v1, v2, res; + if (!tonumeral(e1, &v1) || !tonumeral(e2, &v2) || !validop(op, &v1, &v2)) + return 0; /* non-numeric operands or not safe to fold */ + luaO_arith(fs->ls->L, op, &v1, &v2, &res); /* does operation */ + if (ttisinteger(&res)) { + e1->k = VKINT; + e1->u.ival = ivalue(&res); + } + else { /* folds neither NaN nor 0.0 (to avoid problems with -0.0) */ + lua_Number n = fltvalue(&res); + if (luai_numisnan(n) || n == 0) + return 0; + e1->k = VKFLT; + e1->u.nval = n; + } + return 1; +} + + +/* +** Emit code for unary expressions that "produce values" +** (everything but 'not'). +** Expression to produce final result will be encoded in 'e'. +*/ +static void codeunexpval (FuncState *fs, OpCode op, expdesc *e, int line) { + int r = luaK_exp2anyreg(fs, e); /* opcodes operate only on registers */ + freeexp(fs, e); + e->u.info = luaK_codeABC(fs, op, 0, r, 0); /* generate opcode */ + e->k = VRELOCABLE; /* all those operations are relocatable */ + luaK_fixline(fs, line); +} + + +/* +** Emit code for binary expressions that "produce values" +** (everything but logical operators 'and'/'or' and comparison +** operators). +** Expression to produce final result will be encoded in 'e1'. +** Because 'luaK_exp2RK' can free registers, its calls must be +** in "stack order" (that is, first on 'e2', which may have more +** recent registers to be released). +*/ +static void codebinexpval (FuncState *fs, OpCode op, + expdesc *e1, expdesc *e2, int line) { + int rk2 = luaK_exp2RK(fs, e2); /* both operands are "RK" */ + int rk1 = luaK_exp2RK(fs, e1); + freeexps(fs, e1, e2); + e1->u.info = luaK_codeABC(fs, op, 0, rk1, rk2); /* generate opcode */ + e1->k = VRELOCABLE; /* all those operations are relocatable */ + luaK_fixline(fs, line); +} + + +/* +** Emit code for comparisons. +** 'e1' was already put in R/K form by 'luaK_infix'. +*/ +static void codecomp (FuncState *fs, BinOpr opr, expdesc *e1, expdesc *e2) { + int rk1 = (e1->k == VK) ? RKASK(e1->u.info) + : check_exp(e1->k == VNONRELOC, e1->u.info); + int rk2 = luaK_exp2RK(fs, e2); + freeexps(fs, e1, e2); + switch (opr) { + case OPR_NE: { /* '(a ~= b)' ==> 'not (a == b)' */ + e1->u.info = condjump(fs, OP_EQ, 0, rk1, rk2); + break; + } + case OPR_GT: case OPR_GE: { + /* '(a > b)' ==> '(b < a)'; '(a >= b)' ==> '(b <= a)' */ + OpCode op = cast(OpCode, (opr - OPR_NE) + OP_EQ); + e1->u.info = condjump(fs, op, 1, rk2, rk1); /* invert operands */ + break; + } + default: { /* '==', '<', '<=' use their own opcodes */ + OpCode op = cast(OpCode, (opr - OPR_EQ) + OP_EQ); + e1->u.info = condjump(fs, op, 1, rk1, rk2); + break; + } + } + e1->k = VJMP; +} + + +/* +** Apply prefix operation 'op' to expression 'e'. +*/ +void luaK_prefix (FuncState *fs, UnOpr op, expdesc *e, int line) { + static const expdesc ef = {VKINT, {0}, NO_JUMP, NO_JUMP}; + switch (op) { + case OPR_MINUS: case OPR_BNOT: /* use 'ef' as fake 2nd operand */ + if (constfolding(fs, op + LUA_OPUNM, e, &ef)) + break; + /* FALLTHROUGH */ + case OPR_LEN: + codeunexpval(fs, cast(OpCode, op + OP_UNM), e, line); + break; + case OPR_NOT: codenot(fs, e); break; + default: lua_assert(0); + } +} + + +/* +** Process 1st operand 'v' of binary operation 'op' before reading +** 2nd operand. +*/ +void luaK_infix (FuncState *fs, BinOpr op, expdesc *v) { + switch (op) { + case OPR_AND: { + luaK_goiftrue(fs, v); /* go ahead only if 'v' is true */ + break; + } + case OPR_OR: { + luaK_goiffalse(fs, v); /* go ahead only if 'v' is false */ + break; + } + case OPR_CONCAT: { + luaK_exp2nextreg(fs, v); /* operand must be on the 'stack' */ + break; + } + case OPR_ADD: case OPR_SUB: + case OPR_MUL: case OPR_DIV: case OPR_IDIV: + case OPR_MOD: case OPR_POW: + case OPR_BAND: case OPR_BOR: case OPR_BXOR: + case OPR_SHL: case OPR_SHR: { + if (!tonumeral(v, NULL)) + luaK_exp2RK(fs, v); + /* else keep numeral, which may be folded with 2nd operand */ + break; + } + default: { + luaK_exp2RK(fs, v); + break; + } + } +} + + +/* +** Finalize code for binary operation, after reading 2nd operand. +** For '(a .. b .. c)' (which is '(a .. (b .. c))', because +** concatenation is right associative), merge second CONCAT into first +** one. +*/ +void luaK_posfix (FuncState *fs, BinOpr op, + expdesc *e1, expdesc *e2, int line) { + switch (op) { + case OPR_AND: { + lua_assert(e1->t == NO_JUMP); /* list closed by 'luK_infix' */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->f, e1->f); + *e1 = *e2; + break; + } + case OPR_OR: { + lua_assert(e1->f == NO_JUMP); /* list closed by 'luK_infix' */ + luaK_dischargevars(fs, e2); + luaK_concat(fs, &e2->t, e1->t); + *e1 = *e2; + break; + } + case OPR_CONCAT: { + luaK_exp2val(fs, e2); + if (e2->k == VRELOCABLE && + GET_OPCODE(getinstruction(fs, e2)) == OP_CONCAT) { + lua_assert(e1->u.info == GETARG_B(getinstruction(fs, e2))-1); + freeexp(fs, e1); + SETARG_B(getinstruction(fs, e2), e1->u.info); + e1->k = VRELOCABLE; e1->u.info = e2->u.info; + } + else { + luaK_exp2nextreg(fs, e2); /* operand must be on the 'stack' */ + codebinexpval(fs, OP_CONCAT, e1, e2, line); + } + break; + } + case OPR_ADD: case OPR_SUB: case OPR_MUL: case OPR_DIV: + case OPR_IDIV: case OPR_MOD: case OPR_POW: + case OPR_BAND: case OPR_BOR: case OPR_BXOR: + case OPR_SHL: case OPR_SHR: { + if (!constfolding(fs, op + LUA_OPADD, e1, e2)) + codebinexpval(fs, cast(OpCode, op + OP_ADD), e1, e2, line); + break; + } + case OPR_EQ: case OPR_LT: case OPR_LE: + case OPR_NE: case OPR_GT: case OPR_GE: { + codecomp(fs, op, e1, e2); + break; + } + default: lua_assert(0); + } +} + + +/* +** Change line information associated with current position. +*/ +void luaK_fixline (FuncState *fs, int line) { + fs->f->lineinfo[fs->pc - 1] = line; +} + + +/* +** Emit a SETLIST instruction. +** 'base' is register that keeps table; +** 'nelems' is #table plus those to be stored now; +** 'tostore' is number of values (in registers 'base + 1',...) to add to +** table (or LUA_MULTRET to add up to stack top). +*/ +void luaK_setlist (FuncState *fs, int base, int nelems, int tostore) { + int c = (nelems - 1)/LFIELDS_PER_FLUSH + 1; + int b = (tostore == LUA_MULTRET) ? 0 : tostore; + lua_assert(tostore != 0 && tostore <= LFIELDS_PER_FLUSH); + if (c <= MAXARG_C) + luaK_codeABC(fs, OP_SETLIST, base, b, c); + else if (c <= MAXARG_Ax) { + luaK_codeABC(fs, OP_SETLIST, base, b, 0); + codeextraarg(fs, c); + } + else + luaX_syntaxerror(fs->ls, "constructor too long"); + fs->freereg = base + 1; /* free registers with list values */ +} + diff --git a/src/lua/lcode.h b/src/lua/lcode.h new file mode 100644 index 000000000000..882dc9c156ef --- /dev/null +++ b/src/lua/lcode.h @@ -0,0 +1,88 @@ +/* +** $Id: lcode.h,v 1.64.1.1 2017/04/19 17:20:42 roberto Exp $ +** Code generator for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lcode_h +#define lcode_h + +#include "llex.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" + + +/* +** Marks the end of a patch list. It is an invalid value both as an absolute +** address, and as a list link (would link an element to itself). +*/ +#define NO_JUMP (-1) + + +/* +** grep "ORDER OPR" if you change these enums (ORDER OP) +*/ +typedef enum BinOpr { + OPR_ADD, OPR_SUB, OPR_MUL, OPR_MOD, OPR_POW, + OPR_DIV, + OPR_IDIV, + OPR_BAND, OPR_BOR, OPR_BXOR, + OPR_SHL, OPR_SHR, + OPR_CONCAT, + OPR_EQ, OPR_LT, OPR_LE, + OPR_NE, OPR_GT, OPR_GE, + OPR_AND, OPR_OR, + OPR_NOBINOPR +} BinOpr; + + +typedef enum UnOpr { OPR_MINUS, OPR_BNOT, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; + + +/* get (pointer to) instruction of given 'expdesc' */ +#define getinstruction(fs,e) ((fs)->f->code[(e)->u.info]) + +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) + +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) + +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) + +LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); +LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); +LUAI_FUNC int luaK_codek (FuncState *fs, int reg, int k); +LUAI_FUNC void luaK_fixline (FuncState *fs, int line); +LUAI_FUNC void luaK_nil (FuncState *fs, int from, int n); +LUAI_FUNC void luaK_reserveregs (FuncState *fs, int n); +LUAI_FUNC void luaK_checkstack (FuncState *fs, int n); +LUAI_FUNC int luaK_stringK (FuncState *fs, TString *s); +LUAI_FUNC int luaK_intK (FuncState *fs, lua_Integer n); +LUAI_FUNC void luaK_dischargevars (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2anyreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2anyregup (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2nextreg (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_exp2val (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_exp2RK (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_self (FuncState *fs, expdesc *e, expdesc *key); +LUAI_FUNC void luaK_indexed (FuncState *fs, expdesc *t, expdesc *k); +LUAI_FUNC void luaK_goiftrue (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_goiffalse (FuncState *fs, expdesc *e); +LUAI_FUNC void luaK_storevar (FuncState *fs, expdesc *var, expdesc *e); +LUAI_FUNC void luaK_setreturns (FuncState *fs, expdesc *e, int nresults); +LUAI_FUNC void luaK_setoneret (FuncState *fs, expdesc *e); +LUAI_FUNC int luaK_jump (FuncState *fs); +LUAI_FUNC void luaK_ret (FuncState *fs, int first, int nret); +LUAI_FUNC void luaK_patchlist (FuncState *fs, int list, int target); +LUAI_FUNC void luaK_patchtohere (FuncState *fs, int list); +LUAI_FUNC void luaK_patchclose (FuncState *fs, int list, int level); +LUAI_FUNC void luaK_concat (FuncState *fs, int *l1, int l2); +LUAI_FUNC int luaK_getlabel (FuncState *fs); +LUAI_FUNC void luaK_prefix (FuncState *fs, UnOpr op, expdesc *v, int line); +LUAI_FUNC void luaK_infix (FuncState *fs, BinOpr op, expdesc *v); +LUAI_FUNC void luaK_posfix (FuncState *fs, BinOpr op, expdesc *v1, + expdesc *v2, int line); +LUAI_FUNC void luaK_setlist (FuncState *fs, int base, int nelems, int tostore); + + +#endif diff --git a/src/lua/lcorolib.c b/src/lua/lcorolib.c new file mode 100644 index 000000000000..0b17af9e343a --- /dev/null +++ b/src/lua/lcorolib.c @@ -0,0 +1,168 @@ +/* +** $Id: lcorolib.c,v 1.10.1.1 2017/04/19 17:20:42 roberto Exp $ +** Coroutine Library +** See Copyright Notice in lua.h +*/ + +#define lcorolib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +static lua_State *getco (lua_State *L) { + lua_State *co = lua_tothread(L, 1); + luaL_argcheck(L, co, 1, "thread expected"); + return co; +} + + +static int auxresume (lua_State *L, lua_State *co, int narg) { + int status; + if (!lua_checkstack(co, narg)) { + lua_pushliteral(L, "too many arguments to resume"); + return -1; /* error flag */ + } + if (lua_status(co) == LUA_OK && lua_gettop(co) == 0) { + lua_pushliteral(L, "cannot resume dead coroutine"); + return -1; /* error flag */ + } + lua_xmove(L, co, narg); + status = lua_resume(co, L, narg); + if (status == LUA_OK || status == LUA_YIELD) { + int nres = lua_gettop(co); + if (!lua_checkstack(L, nres + 1)) { + lua_pop(co, nres); /* remove results anyway */ + lua_pushliteral(L, "too many results to resume"); + return -1; /* error flag */ + } + lua_xmove(co, L, nres); /* move yielded values */ + return nres; + } + else { + lua_xmove(co, L, 1); /* move error message */ + return -1; /* error flag */ + } +} + + +static int luaB_coresume (lua_State *L) { + lua_State *co = getco(L); + int r; + r = auxresume(L, co, lua_gettop(L) - 1); + if (r < 0) { + lua_pushboolean(L, 0); + lua_insert(L, -2); + return 2; /* return false + error message */ + } + else { + lua_pushboolean(L, 1); + lua_insert(L, -(r + 1)); + return r + 1; /* return true + 'resume' returns */ + } +} + + +static int luaB_auxwrap (lua_State *L) { + lua_State *co = lua_tothread(L, lua_upvalueindex(1)); + int r = auxresume(L, co, lua_gettop(L)); + if (r < 0) { + if (lua_type(L, -1) == LUA_TSTRING) { /* error object is a string? */ + luaL_where(L, 1); /* add extra info */ + lua_insert(L, -2); + lua_concat(L, 2); + } + return lua_error(L); /* propagate error */ + } + return r; +} + + +static int luaB_cocreate (lua_State *L) { + lua_State *NL; + luaL_checktype(L, 1, LUA_TFUNCTION); + NL = lua_newthread(L); + lua_pushvalue(L, 1); /* move function to top */ + lua_xmove(L, NL, 1); /* move function from L to NL */ + return 1; +} + + +static int luaB_cowrap (lua_State *L) { + luaB_cocreate(L); + lua_pushcclosure(L, luaB_auxwrap, 1); + return 1; +} + + +static int luaB_yield (lua_State *L) { + return lua_yield(L, lua_gettop(L)); +} + + +static int luaB_costatus (lua_State *L) { + lua_State *co = getco(L); + if (L == co) lua_pushliteral(L, "running"); + else { + switch (lua_status(co)) { + case LUA_YIELD: + lua_pushliteral(L, "suspended"); + break; + case LUA_OK: { + lua_Debug ar; + if (lua_getstack(co, 0, &ar) > 0) /* does it have frames? */ + lua_pushliteral(L, "normal"); /* it is running */ + else if (lua_gettop(co) == 0) + lua_pushliteral(L, "dead"); + else + lua_pushliteral(L, "suspended"); /* initial state */ + break; + } + default: /* some error occurred */ + lua_pushliteral(L, "dead"); + break; + } + } + return 1; +} + + +static int luaB_yieldable (lua_State *L) { + lua_pushboolean(L, lua_isyieldable(L)); + return 1; +} + + +static int luaB_corunning (lua_State *L) { + int ismain = lua_pushthread(L); + lua_pushboolean(L, ismain); + return 2; +} + + +static const luaL_Reg co_funcs[] = { + {"create", luaB_cocreate}, + {"resume", luaB_coresume}, + {"running", luaB_corunning}, + {"status", luaB_costatus}, + {"wrap", luaB_cowrap}, + {"yield", luaB_yield}, + {"isyieldable", luaB_yieldable}, + {NULL, NULL} +}; + + + +LUAMOD_API int luaopen_coroutine (lua_State *L) { + luaL_newlib(L, co_funcs); + return 1; +} + diff --git a/src/lua/lctype.c b/src/lua/lctype.c new file mode 100644 index 000000000000..f8ad7a2edf6e --- /dev/null +++ b/src/lua/lctype.c @@ -0,0 +1,55 @@ +/* +** $Id: lctype.c,v 1.12.1.1 2017/04/19 17:20:42 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#define lctype_c +#define LUA_CORE + +#include "lprefix.h" + + +#include "lctype.h" + +#if !LUA_USE_CTYPE /* { */ + +#include + +LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { + 0x00, /* EOZ */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, +}; + +#endif /* } */ diff --git a/src/lua/lctype.h b/src/lua/lctype.h new file mode 100644 index 000000000000..b09b21a337c5 --- /dev/null +++ b/src/lua/lctype.h @@ -0,0 +1,95 @@ +/* +** $Id: lctype.h,v 1.12.1.1 2013/04/12 18:48:47 roberto Exp $ +** 'ctype' functions for Lua +** See Copyright Notice in lua.h +*/ + +#ifndef lctype_h +#define lctype_h + +#include "lua.h" + + +/* +** WARNING: the functions defined here do not necessarily correspond +** to the similar functions in the standard C ctype.h. They are +** optimized for the specific needs of Lua +*/ + +#if !defined(LUA_USE_CTYPE) + +#if 'A' == 65 && '0' == 48 +/* ASCII case: can use its own tables; faster and fixed */ +#define LUA_USE_CTYPE 0 +#else +/* must use standard C ctype */ +#define LUA_USE_CTYPE 1 +#endif + +#endif + + +#if !LUA_USE_CTYPE /* { */ + +#include + +#include "llimits.h" + + +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 + + +#define MASK(B) (1 << (B)) + + +/* +** add 1 to char to allow index -1 (EOZ) +*/ +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) + +/* +** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' +*/ +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) + +/* +** this 'ltolower' only works for alphabetic characters +*/ +#define ltolower(c) ((c) | ('A' ^ 'a')) + + +/* two more entries for 0 and -1 (EOZ) */ +LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; + + +#else /* }{ */ + +/* +** use standard C ctypes +*/ + +#include + + +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) + +#define ltolower(c) (tolower(c)) + +#endif /* } */ + +#endif + diff --git a/src/lua/ldblib.c b/src/lua/ldblib.c new file mode 100644 index 000000000000..9d29afb0a898 --- /dev/null +++ b/src/lua/ldblib.c @@ -0,0 +1,456 @@ +/* +** $Id: ldblib.c,v 1.151.1.1 2017/04/19 17:20:42 roberto Exp $ +** Interface from Lua to its debug API +** See Copyright Notice in lua.h +*/ + +#define ldblib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** The hook table at registry[&HOOKKEY] maps threads to their current +** hook function. (We only need the unique address of 'HOOKKEY'.) +*/ +static const int HOOKKEY = 0; + + +/* +** If L1 != L, L1 can be in any state, and therefore there are no +** guarantees about its stack space; any push in L1 must be +** checked. +*/ +static void checkstack (lua_State *L, lua_State *L1, int n) { + if (L != L1 && !lua_checkstack(L1, n)) + luaL_error(L, "stack overflow"); +} + + +static int db_getregistry (lua_State *L) { + lua_pushvalue(L, LUA_REGISTRYINDEX); + return 1; +} + + +static int db_getmetatable (lua_State *L) { + luaL_checkany(L, 1); + if (!lua_getmetatable(L, 1)) { + lua_pushnil(L); /* no metatable */ + } + return 1; +} + + +static int db_setmetatable (lua_State *L) { + int t = lua_type(L, 2); + luaL_argcheck(L, t == LUA_TNIL || t == LUA_TTABLE, 2, + "nil or table expected"); + lua_settop(L, 2); + lua_setmetatable(L, 1); + return 1; /* return 1st argument */ +} + + +static int db_getuservalue (lua_State *L) { + if (lua_type(L, 1) != LUA_TUSERDATA) + lua_pushnil(L); + else + lua_getuservalue(L, 1); + return 1; +} + + +static int db_setuservalue (lua_State *L) { + luaL_checktype(L, 1, LUA_TUSERDATA); + luaL_checkany(L, 2); + lua_settop(L, 2); + lua_setuservalue(L, 1); + return 1; +} + + +/* +** Auxiliary function used by several library functions: check for +** an optional thread as function's first argument and set 'arg' with +** 1 if this argument is present (so that functions can skip it to +** access their other arguments) +*/ +static lua_State *getthread (lua_State *L, int *arg) { + if (lua_isthread(L, 1)) { + *arg = 1; + return lua_tothread(L, 1); + } + else { + *arg = 0; + return L; /* function will operate over current thread */ + } +} + + +/* +** Variations of 'lua_settable', used by 'db_getinfo' to put results +** from 'lua_getinfo' into result table. Key is always a string; +** value can be a string, an int, or a boolean. +*/ +static void settabss (lua_State *L, const char *k, const char *v) { + lua_pushstring(L, v); + lua_setfield(L, -2, k); +} + +static void settabsi (lua_State *L, const char *k, int v) { + lua_pushinteger(L, v); + lua_setfield(L, -2, k); +} + +static void settabsb (lua_State *L, const char *k, int v) { + lua_pushboolean(L, v); + lua_setfield(L, -2, k); +} + + +/* +** In function 'db_getinfo', the call to 'lua_getinfo' may push +** results on the stack; later it creates the result table to put +** these objects. Function 'treatstackoption' puts the result from +** 'lua_getinfo' on top of the result table so that it can call +** 'lua_setfield'. +*/ +static void treatstackoption (lua_State *L, lua_State *L1, const char *fname) { + if (L == L1) + lua_rotate(L, -2, 1); /* exchange object and table */ + else + lua_xmove(L1, L, 1); /* move object to the "main" stack */ + lua_setfield(L, -2, fname); /* put object into table */ +} + + +/* +** Calls 'lua_getinfo' and collects all results in a new table. +** L1 needs stack space for an optional input (function) plus +** two optional outputs (function and line table) from function +** 'lua_getinfo'. +*/ +static int db_getinfo (lua_State *L) { + lua_Debug ar; + int arg; + lua_State *L1 = getthread(L, &arg); + const char *options = luaL_optstring(L, arg+2, "flnStu"); + checkstack(L, L1, 3); + if (lua_isfunction(L, arg + 1)) { /* info about a function? */ + options = lua_pushfstring(L, ">%s", options); /* add '>' to 'options' */ + lua_pushvalue(L, arg + 1); /* move function to 'L1' stack */ + lua_xmove(L, L1, 1); + } + else { /* stack level */ + if (!lua_getstack(L1, (int)luaL_checkinteger(L, arg + 1), &ar)) { + lua_pushnil(L); /* level out of range */ + return 1; + } + } + if (!lua_getinfo(L1, options, &ar)) + return luaL_argerror(L, arg+2, "invalid option"); + lua_newtable(L); /* table to collect results */ + if (strchr(options, 'S')) { + settabss(L, "source", ar.source); + settabss(L, "short_src", ar.short_src); + settabsi(L, "linedefined", ar.linedefined); + settabsi(L, "lastlinedefined", ar.lastlinedefined); + settabss(L, "what", ar.what); + } + if (strchr(options, 'l')) + settabsi(L, "currentline", ar.currentline); + if (strchr(options, 'u')) { + settabsi(L, "nups", ar.nups); + settabsi(L, "nparams", ar.nparams); + settabsb(L, "isvararg", ar.isvararg); + } + if (strchr(options, 'n')) { + settabss(L, "name", ar.name); + settabss(L, "namewhat", ar.namewhat); + } + if (strchr(options, 't')) + settabsb(L, "istailcall", ar.istailcall); + if (strchr(options, 'L')) + treatstackoption(L, L1, "activelines"); + if (strchr(options, 'f')) + treatstackoption(L, L1, "func"); + return 1; /* return table */ +} + + +static int db_getlocal (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + const char *name; + int nvar = (int)luaL_checkinteger(L, arg + 2); /* local-variable index */ + if (lua_isfunction(L, arg + 1)) { /* function argument? */ + lua_pushvalue(L, arg + 1); /* push function */ + lua_pushstring(L, lua_getlocal(L, NULL, nvar)); /* push local name */ + return 1; /* return only name (there is no value) */ + } + else { /* stack-level argument */ + int level = (int)luaL_checkinteger(L, arg + 1); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + checkstack(L, L1, 1); + name = lua_getlocal(L1, &ar, nvar); + if (name) { + lua_xmove(L1, L, 1); /* move local value */ + lua_pushstring(L, name); /* push name */ + lua_rotate(L, -2, 1); /* re-order */ + return 2; + } + else { + lua_pushnil(L); /* no name (nor value) */ + return 1; + } + } +} + + +static int db_setlocal (lua_State *L) { + int arg; + const char *name; + lua_State *L1 = getthread(L, &arg); + lua_Debug ar; + int level = (int)luaL_checkinteger(L, arg + 1); + int nvar = (int)luaL_checkinteger(L, arg + 2); + if (!lua_getstack(L1, level, &ar)) /* out of range? */ + return luaL_argerror(L, arg+1, "level out of range"); + luaL_checkany(L, arg+3); + lua_settop(L, arg+3); + checkstack(L, L1, 1); + lua_xmove(L, L1, 1); + name = lua_setlocal(L1, &ar, nvar); + if (name == NULL) + lua_pop(L1, 1); /* pop value (if not popped by 'lua_setlocal') */ + lua_pushstring(L, name); + return 1; +} + + +/* +** get (if 'get' is true) or set an upvalue from a closure +*/ +static int auxupvalue (lua_State *L, int get) { + const char *name; + int n = (int)luaL_checkinteger(L, 2); /* upvalue index */ + luaL_checktype(L, 1, LUA_TFUNCTION); /* closure */ + name = get ? lua_getupvalue(L, 1, n) : lua_setupvalue(L, 1, n); + if (name == NULL) return 0; + lua_pushstring(L, name); + lua_insert(L, -(get+1)); /* no-op if get is false */ + return get + 1; +} + + +static int db_getupvalue (lua_State *L) { + return auxupvalue(L, 1); +} + + +static int db_setupvalue (lua_State *L) { + luaL_checkany(L, 3); + return auxupvalue(L, 0); +} + + +/* +** Check whether a given upvalue from a given closure exists and +** returns its index +*/ +static int checkupval (lua_State *L, int argf, int argnup) { + int nup = (int)luaL_checkinteger(L, argnup); /* upvalue index */ + luaL_checktype(L, argf, LUA_TFUNCTION); /* closure */ + luaL_argcheck(L, (lua_getupvalue(L, argf, nup) != NULL), argnup, + "invalid upvalue index"); + return nup; +} + + +static int db_upvalueid (lua_State *L) { + int n = checkupval(L, 1, 2); + lua_pushlightuserdata(L, lua_upvalueid(L, 1, n)); + return 1; +} + + +static int db_upvaluejoin (lua_State *L) { + int n1 = checkupval(L, 1, 2); + int n2 = checkupval(L, 3, 4); + luaL_argcheck(L, !lua_iscfunction(L, 1), 1, "Lua function expected"); + luaL_argcheck(L, !lua_iscfunction(L, 3), 3, "Lua function expected"); + lua_upvaluejoin(L, 1, n1, 3, n2); + return 0; +} + + +/* +** Call hook function registered at hook table for the current +** thread (if there is one) +*/ +static void hookf (lua_State *L, lua_Debug *ar) { + static const char *const hooknames[] = + {"call", "return", "line", "count", "tail call"}; + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + lua_pushthread(L); + if (lua_rawget(L, -2) == LUA_TFUNCTION) { /* is there a hook function? */ + lua_pushstring(L, hooknames[(int)ar->event]); /* push event name */ + if (ar->currentline >= 0) + lua_pushinteger(L, ar->currentline); /* push current line */ + else lua_pushnil(L); + lua_assert(lua_getinfo(L, "lS", ar)); + lua_call(L, 2, 0); /* call hook function */ + } +} + + +/* +** Convert a string mask (for 'sethook') into a bit mask +*/ +static int makemask (const char *smask, int count) { + int mask = 0; + if (strchr(smask, 'c')) mask |= LUA_MASKCALL; + if (strchr(smask, 'r')) mask |= LUA_MASKRET; + if (strchr(smask, 'l')) mask |= LUA_MASKLINE; + if (count > 0) mask |= LUA_MASKCOUNT; + return mask; +} + + +/* +** Convert a bit mask (for 'gethook') into a string mask +*/ +static char *unmakemask (int mask, char *smask) { + int i = 0; + if (mask & LUA_MASKCALL) smask[i++] = 'c'; + if (mask & LUA_MASKRET) smask[i++] = 'r'; + if (mask & LUA_MASKLINE) smask[i++] = 'l'; + smask[i] = '\0'; + return smask; +} + + +static int db_sethook (lua_State *L) { + int arg, mask, count; + lua_Hook func; + lua_State *L1 = getthread(L, &arg); + if (lua_isnoneornil(L, arg+1)) { /* no hook? */ + lua_settop(L, arg+1); + func = NULL; mask = 0; count = 0; /* turn off hooks */ + } + else { + const char *smask = luaL_checkstring(L, arg+2); + luaL_checktype(L, arg+1, LUA_TFUNCTION); + count = (int)luaL_optinteger(L, arg + 3, 0); + func = hookf; mask = makemask(smask, count); + } + if (lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY) == LUA_TNIL) { + lua_createtable(L, 0, 2); /* create a hook table */ + lua_pushvalue(L, -1); + lua_rawsetp(L, LUA_REGISTRYINDEX, &HOOKKEY); /* set it in position */ + lua_pushstring(L, "k"); + lua_setfield(L, -2, "__mode"); /** hooktable.__mode = "k" */ + lua_pushvalue(L, -1); + lua_setmetatable(L, -2); /* setmetatable(hooktable) = hooktable */ + } + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); /* key (thread) */ + lua_pushvalue(L, arg + 1); /* value (hook function) */ + lua_rawset(L, -3); /* hooktable[L1] = new Lua hook */ + lua_sethook(L1, func, mask, count); + return 0; +} + + +static int db_gethook (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + char buff[5]; + int mask = lua_gethookmask(L1); + lua_Hook hook = lua_gethook(L1); + if (hook == NULL) /* no hook? */ + lua_pushnil(L); + else if (hook != hookf) /* external hook? */ + lua_pushliteral(L, "external hook"); + else { /* hook table must exist */ + lua_rawgetp(L, LUA_REGISTRYINDEX, &HOOKKEY); + checkstack(L, L1, 1); + lua_pushthread(L1); lua_xmove(L1, L, 1); + lua_rawget(L, -2); /* 1st result = hooktable[L1] */ + lua_remove(L, -2); /* remove hook table */ + } + lua_pushstring(L, unmakemask(mask, buff)); /* 2nd result = mask */ + lua_pushinteger(L, lua_gethookcount(L1)); /* 3rd result = count */ + return 3; +} + + +static int db_debug (lua_State *L) { + for (;;) { + char buffer[250]; + lua_writestringerror("%s", "lua_debug> "); + if (fgets(buffer, sizeof(buffer), stdin) == 0 || + strcmp(buffer, "cont\n") == 0) + return 0; + if (luaL_loadbuffer(L, buffer, strlen(buffer), "=(debug command)") || + lua_pcall(L, 0, 0, 0)) + lua_writestringerror("%s\n", lua_tostring(L, -1)); + lua_settop(L, 0); /* remove eventual returns */ + } +} + + +static int db_traceback (lua_State *L) { + int arg; + lua_State *L1 = getthread(L, &arg); + const char *msg = lua_tostring(L, arg + 1); + if (msg == NULL && !lua_isnoneornil(L, arg + 1)) /* non-string 'msg'? */ + lua_pushvalue(L, arg + 1); /* return it untouched */ + else { + int level = (int)luaL_optinteger(L, arg + 2, (L == L1) ? 1 : 0); + luaL_traceback(L, L1, msg, level); + } + return 1; +} + + +static const luaL_Reg dblib[] = { + {"debug", db_debug}, + {"getuservalue", db_getuservalue}, + {"gethook", db_gethook}, + {"getinfo", db_getinfo}, + {"getlocal", db_getlocal}, + {"getregistry", db_getregistry}, + {"getmetatable", db_getmetatable}, + {"getupvalue", db_getupvalue}, + {"upvaluejoin", db_upvaluejoin}, + {"upvalueid", db_upvalueid}, + {"setuservalue", db_setuservalue}, + {"sethook", db_sethook}, + {"setlocal", db_setlocal}, + {"setmetatable", db_setmetatable}, + {"setupvalue", db_setupvalue}, + {"traceback", db_traceback}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_debug (lua_State *L) { + luaL_newlib(L, dblib); + return 1; +} + diff --git a/src/lua/ldebug.c b/src/lua/ldebug.c new file mode 100644 index 000000000000..bb0e1d4aceda --- /dev/null +++ b/src/lua/ldebug.c @@ -0,0 +1,700 @@ +/* +** $Id: ldebug.c,v 2.121.1.2 2017/07/10 17:21:50 roberto Exp $ +** Debug Interface +** See Copyright Notice in lua.h +*/ + +#define ldebug_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + + +#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) + + +/* Active Lua function (given call info) */ +#define ci_func(ci) (clLvalue((ci)->func)) + + +static const char *funcnamefromcode (lua_State *L, CallInfo *ci, + const char **name); + + +static int currentpc (CallInfo *ci) { + lua_assert(isLua(ci)); + return pcRel(ci->u.l.savedpc, ci_func(ci)->p); +} + + +static int currentline (CallInfo *ci) { + return getfuncline(ci_func(ci)->p, currentpc(ci)); +} + + +/* +** If function yielded, its 'func' can be in the 'extra' field. The +** next function restores 'func' to its correct value for debugging +** purposes. (It exchanges 'func' and 'extra'; so, when called again, +** after debugging, it also "re-restores" ** 'func' to its altered value. +*/ +static void swapextra (lua_State *L) { + if (L->status == LUA_YIELD) { + CallInfo *ci = L->ci; /* get function that yielded */ + StkId temp = ci->func; /* exchange its 'func' and 'extra' values */ + ci->func = restorestack(L, ci->extra); + ci->extra = savestack(L, temp); + } +} + + +/* +** This function can be called asynchronously (e.g. during a signal). +** Fields 'oldpc', 'basehookcount', and 'hookcount' (set by +** 'resethookcount') are for debug only, and it is no problem if they +** get arbitrary values (causes at most one wrong hook call). 'hookmask' +** is an atomic value. We assume that pointers are atomic too (e.g., gcc +** ensures that for all platforms where it runs). Moreover, 'hook' is +** always checked before being called (see 'luaD_hook'). +*/ +LUA_API void lua_sethook (lua_State *L, lua_Hook func, int mask, int count) { + if (func == NULL || mask == 0) { /* turn off hooks? */ + mask = 0; + func = NULL; + } + if (isLua(L->ci)) + L->oldpc = L->ci->u.l.savedpc; + L->hook = func; + L->basehookcount = count; + resethookcount(L); + L->hookmask = cast_byte(mask); +} + + +LUA_API lua_Hook lua_gethook (lua_State *L) { + return L->hook; +} + + +LUA_API int lua_gethookmask (lua_State *L) { + return L->hookmask; +} + + +LUA_API int lua_gethookcount (lua_State *L) { + return L->basehookcount; +} + + +LUA_API int lua_getstack (lua_State *L, int level, lua_Debug *ar) { + int status; + CallInfo *ci; + if (level < 0) return 0; /* invalid (negative) level */ + lua_lock(L); + for (ci = L->ci; level > 0 && ci != &L->base_ci; ci = ci->previous) + level--; + if (level == 0 && ci != &L->base_ci) { /* level found? */ + status = 1; + ar->i_ci = ci; + } + else status = 0; /* no such level */ + lua_unlock(L); + return status; +} + + +static const char *upvalname (Proto *p, int uv) { + TString *s = check_exp(uv < p->sizeupvalues, p->upvalues[uv].name); + if (s == NULL) return "?"; + else return getstr(s); +} + + +static const char *findvararg (CallInfo *ci, int n, StkId *pos) { + int nparams = clLvalue(ci->func)->p->numparams; + int nvararg = cast_int(ci->u.l.base - ci->func) - nparams; + if (n <= -nvararg) + return NULL; /* no such vararg */ + else { + *pos = ci->func + nparams - n; + return "(*vararg)"; /* generic name for any vararg */ + } +} + + +static const char *findlocal (lua_State *L, CallInfo *ci, int n, + StkId *pos) { + const char *name = NULL; + StkId base; + if (isLua(ci)) { + if (n < 0) /* access to vararg values? */ + return findvararg(ci, n, pos); + else { + base = ci->u.l.base; + name = luaF_getlocalname(ci_func(ci)->p, n, currentpc(ci)); + } + } + else + base = ci->func + 1; + if (name == NULL) { /* no 'standard' name? */ + StkId limit = (ci == L->ci) ? L->top : ci->next->func; + if (limit - base >= n && n > 0) /* is 'n' inside 'ci' stack? */ + name = "(*temporary)"; /* generic name for any valid slot */ + else + return NULL; /* no name */ + } + *pos = base + (n - 1); + return name; +} + + +LUA_API const char *lua_getlocal (lua_State *L, const lua_Debug *ar, int n) { + const char *name; + lua_lock(L); + swapextra(L); + if (ar == NULL) { /* information about non-active function? */ + if (!isLfunction(L->top - 1)) /* not a Lua function? */ + name = NULL; + else /* consider live variables at function start (parameters) */ + name = luaF_getlocalname(clLvalue(L->top - 1)->p, n, 0); + } + else { /* active function; get information through 'ar' */ + StkId pos = NULL; /* to avoid warnings */ + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobj2s(L, L->top, pos); + api_incr_top(L); + } + } + swapextra(L); + lua_unlock(L); + return name; +} + + +LUA_API const char *lua_setlocal (lua_State *L, const lua_Debug *ar, int n) { + StkId pos = NULL; /* to avoid warnings */ + const char *name; + lua_lock(L); + swapextra(L); + name = findlocal(L, ar->i_ci, n, &pos); + if (name) { + setobjs2s(L, pos, L->top - 1); + L->top--; /* pop value */ + } + swapextra(L); + lua_unlock(L); + return name; +} + + +static void funcinfo (lua_Debug *ar, Closure *cl) { + if (noLuaClosure(cl)) { + ar->source = "=[C]"; + ar->linedefined = -1; + ar->lastlinedefined = -1; + ar->what = "C"; + } + else { + Proto *p = cl->l.p; + ar->source = p->source ? getstr(p->source) : "=?"; + ar->linedefined = p->linedefined; + ar->lastlinedefined = p->lastlinedefined; + ar->what = (ar->linedefined == 0) ? "main" : "Lua"; + } + luaO_chunkid(ar->short_src, ar->source, LUA_IDSIZE); +} + + +static void collectvalidlines (lua_State *L, Closure *f) { + if (noLuaClosure(f)) { + setnilvalue(L->top); + api_incr_top(L); + } + else { + int i; + TValue v; + int *lineinfo = f->l.p->lineinfo; + Table *t = luaH_new(L); /* new table to store active lines */ + sethvalue(L, L->top, t); /* push it on stack */ + api_incr_top(L); + setbvalue(&v, 1); /* boolean 'true' to be the value of all indices */ + for (i = 0; i < f->l.p->sizelineinfo; i++) /* for all lines with code */ + luaH_setint(L, t, lineinfo[i], &v); /* table[line] = true */ + } +} + + +static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name) { + if (ci == NULL) /* no 'ci'? */ + return NULL; /* no info */ + else if (ci->callstatus & CIST_FIN) { /* is this a finalizer? */ + *name = "__gc"; + return "metamethod"; /* report it as such */ + } + /* calling function is a known Lua function? */ + else if (!(ci->callstatus & CIST_TAIL) && isLua(ci->previous)) + return funcnamefromcode(L, ci->previous, name); + else return NULL; /* no way to find a name */ +} + + +static int auxgetinfo (lua_State *L, const char *what, lua_Debug *ar, + Closure *f, CallInfo *ci) { + int status = 1; + for (; *what; what++) { + switch (*what) { + case 'S': { + funcinfo(ar, f); + break; + } + case 'l': { + ar->currentline = (ci && isLua(ci)) ? currentline(ci) : -1; + break; + } + case 'u': { + ar->nups = (f == NULL) ? 0 : f->c.nupvalues; + if (noLuaClosure(f)) { + ar->isvararg = 1; + ar->nparams = 0; + } + else { + ar->isvararg = f->l.p->is_vararg; + ar->nparams = f->l.p->numparams; + } + break; + } + case 't': { + ar->istailcall = (ci) ? ci->callstatus & CIST_TAIL : 0; + break; + } + case 'n': { + ar->namewhat = getfuncname(L, ci, &ar->name); + if (ar->namewhat == NULL) { + ar->namewhat = ""; /* not found */ + ar->name = NULL; + } + break; + } + case 'L': + case 'f': /* handled by lua_getinfo */ + break; + default: status = 0; /* invalid option */ + } + } + return status; +} + + +LUA_API int lua_getinfo (lua_State *L, const char *what, lua_Debug *ar) { + int status; + Closure *cl; + CallInfo *ci; + StkId func; + lua_lock(L); + swapextra(L); + if (*what == '>') { + ci = NULL; + func = L->top - 1; + api_check(L, ttisfunction(func), "function expected"); + what++; /* skip the '>' */ + L->top--; /* pop function */ + } + else { + ci = ar->i_ci; + func = ci->func; + lua_assert(ttisfunction(ci->func)); + } + cl = ttisclosure(func) ? clvalue(func) : NULL; + status = auxgetinfo(L, what, ar, cl, ci); + if (strchr(what, 'f')) { + setobjs2s(L, L->top, func); + api_incr_top(L); + } + swapextra(L); /* correct before option 'L', which can raise a mem. error */ + if (strchr(what, 'L')) + collectvalidlines(L, cl); + lua_unlock(L); + return status; +} + + +/* +** {====================================================== +** Symbolic Execution +** ======================================================= +*/ + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name); + + +/* +** find a "name" for the RK value 'c' +*/ +static void kname (Proto *p, int pc, int c, const char **name) { + if (ISK(c)) { /* is 'c' a constant? */ + TValue *kvalue = &p->k[INDEXK(c)]; + if (ttisstring(kvalue)) { /* literal constant? */ + *name = svalue(kvalue); /* it is its own name */ + return; + } + /* else no reasonable name found */ + } + else { /* 'c' is a register */ + const char *what = getobjname(p, pc, c, name); /* search for 'c' */ + if (what && *what == 'c') { /* found a constant name? */ + return; /* 'name' already filled */ + } + /* else no reasonable name found */ + } + *name = "?"; /* no reasonable name found */ +} + + +static int filterpc (int pc, int jmptarget) { + if (pc < jmptarget) /* is code conditional (inside a jump)? */ + return -1; /* cannot know who sets that register */ + else return pc; /* current position sets that register */ +} + + +/* +** try to find last instruction before 'lastpc' that modified register 'reg' +*/ +static int findsetreg (Proto *p, int lastpc, int reg) { + int pc; + int setreg = -1; /* keep last instruction that changed 'reg' */ + int jmptarget = 0; /* any code before this address is conditional */ + for (pc = 0; pc < lastpc; pc++) { + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + int a = GETARG_A(i); + switch (op) { + case OP_LOADNIL: { + int b = GETARG_B(i); + if (a <= reg && reg <= a + b) /* set registers from 'a' to 'a+b' */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_TFORCALL: { + if (reg >= a + 2) /* affect all regs above its base */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_CALL: + case OP_TAILCALL: { + if (reg >= a) /* affect all registers above base */ + setreg = filterpc(pc, jmptarget); + break; + } + case OP_JMP: { + int b = GETARG_sBx(i); + int dest = pc + 1 + b; + /* jump is forward and do not skip 'lastpc'? */ + if (pc < dest && dest <= lastpc) { + if (dest > jmptarget) + jmptarget = dest; /* update 'jmptarget' */ + } + break; + } + default: + if (testAMode(op) && reg == a) /* any instruction that set A */ + setreg = filterpc(pc, jmptarget); + break; + } + } + return setreg; +} + + +static const char *getobjname (Proto *p, int lastpc, int reg, + const char **name) { + int pc; + *name = luaF_getlocalname(p, reg + 1, lastpc); + if (*name) /* is a local? */ + return "local"; + /* else try symbolic execution */ + pc = findsetreg(p, lastpc, reg); + if (pc != -1) { /* could find instruction? */ + Instruction i = p->code[pc]; + OpCode op = GET_OPCODE(i); + switch (op) { + case OP_MOVE: { + int b = GETARG_B(i); /* move from 'b' to 'a' */ + if (b < GETARG_A(i)) + return getobjname(p, pc, b, name); /* get name for 'b' */ + break; + } + case OP_GETTABUP: + case OP_GETTABLE: { + int k = GETARG_C(i); /* key index */ + int t = GETARG_B(i); /* table index */ + const char *vn = (op == OP_GETTABLE) /* name of indexed variable */ + ? luaF_getlocalname(p, t + 1, pc) + : upvalname(p, t); + kname(p, pc, k, name); + return (vn && strcmp(vn, LUA_ENV) == 0) ? "global" : "field"; + } + case OP_GETUPVAL: { + *name = upvalname(p, GETARG_B(i)); + return "upvalue"; + } + case OP_LOADK: + case OP_LOADKX: { + int b = (op == OP_LOADK) ? GETARG_Bx(i) + : GETARG_Ax(p->code[pc + 1]); + if (ttisstring(&p->k[b])) { + *name = svalue(&p->k[b]); + return "constant"; + } + break; + } + case OP_SELF: { + int k = GETARG_C(i); /* key index */ + kname(p, pc, k, name); + return "method"; + } + default: break; /* go through to return NULL */ + } + } + return NULL; /* could not find reasonable name */ +} + + +/* +** Try to find a name for a function based on the code that called it. +** (Only works when function was called by a Lua function.) +** Returns what the name is (e.g., "for iterator", "method", +** "metamethod") and sets '*name' to point to the name. +*/ +static const char *funcnamefromcode (lua_State *L, CallInfo *ci, + const char **name) { + TMS tm = (TMS)0; /* (initial value avoids warnings) */ + Proto *p = ci_func(ci)->p; /* calling function */ + int pc = currentpc(ci); /* calling instruction index */ + Instruction i = p->code[pc]; /* calling instruction */ + if (ci->callstatus & CIST_HOOKED) { /* was it called inside a hook? */ + *name = "?"; + return "hook"; + } + switch (GET_OPCODE(i)) { + case OP_CALL: + case OP_TAILCALL: + return getobjname(p, pc, GETARG_A(i), name); /* get function name */ + case OP_TFORCALL: { /* for iterator */ + *name = "for iterator"; + return "for iterator"; + } + /* other instructions can do calls through metamethods */ + case OP_SELF: case OP_GETTABUP: case OP_GETTABLE: + tm = TM_INDEX; + break; + case OP_SETTABUP: case OP_SETTABLE: + tm = TM_NEWINDEX; + break; + case OP_ADD: case OP_SUB: case OP_MUL: case OP_MOD: + case OP_POW: case OP_DIV: case OP_IDIV: case OP_BAND: + case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: { + int offset = cast_int(GET_OPCODE(i)) - cast_int(OP_ADD); /* ORDER OP */ + tm = cast(TMS, offset + cast_int(TM_ADD)); /* ORDER TM */ + break; + } + case OP_UNM: tm = TM_UNM; break; + case OP_BNOT: tm = TM_BNOT; break; + case OP_LEN: tm = TM_LEN; break; + case OP_CONCAT: tm = TM_CONCAT; break; + case OP_EQ: tm = TM_EQ; break; + case OP_LT: tm = TM_LT; break; + case OP_LE: tm = TM_LE; break; + default: + return NULL; /* cannot find a reasonable name */ + } + *name = getstr(G(L)->tmname[tm]); + return "metamethod"; +} + +/* }====================================================== */ + + + +/* +** The subtraction of two potentially unrelated pointers is +** not ISO C, but it should not crash a program; the subsequent +** checks are ISO C and ensure a correct result. +*/ +static int isinstack (CallInfo *ci, const TValue *o) { + ptrdiff_t i = o - ci->u.l.base; + return (0 <= i && i < (ci->top - ci->u.l.base) && ci->u.l.base + i == o); +} + + +/* +** Checks whether value 'o' came from an upvalue. (That can only happen +** with instructions OP_GETTABUP/OP_SETTABUP, which operate directly on +** upvalues.) +*/ +static const char *getupvalname (CallInfo *ci, const TValue *o, + const char **name) { + LClosure *c = ci_func(ci); + int i; + for (i = 0; i < c->nupvalues; i++) { + if (c->upvals[i]->v == o) { + *name = upvalname(c->p, i); + return "upvalue"; + } + } + return NULL; +} + + +static const char *varinfo (lua_State *L, const TValue *o) { + const char *name = NULL; /* to avoid warnings */ + CallInfo *ci = L->ci; + const char *kind = NULL; + if (isLua(ci)) { + kind = getupvalname(ci, o, &name); /* check whether 'o' is an upvalue */ + if (!kind && isinstack(ci, o)) /* no? try a register */ + kind = getobjname(ci_func(ci)->p, currentpc(ci), + cast_int(o - ci->u.l.base), &name); + } + return (kind) ? luaO_pushfstring(L, " (%s '%s')", kind, name) : ""; +} + + +l_noret luaG_typeerror (lua_State *L, const TValue *o, const char *op) { + const char *t = luaT_objtypename(L, o); + luaG_runerror(L, "attempt to %s a %s value%s", op, t, varinfo(L, o)); +} + + +l_noret luaG_concaterror (lua_State *L, const TValue *p1, const TValue *p2) { + if (ttisstring(p1) || cvt2str(p1)) p1 = p2; + luaG_typeerror(L, p1, "concatenate"); +} + + +l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, const char *msg) { + lua_Number temp; + if (!tonumber(p1, &temp)) /* first operand is wrong? */ + p2 = p1; /* now second is wrong */ + luaG_typeerror(L, p2, msg); +} + + +/* +** Error when both values are convertible to numbers, but not to integers +*/ +l_noret luaG_tointerror (lua_State *L, const TValue *p1, const TValue *p2) { + lua_Integer temp; + if (!tointeger(p1, &temp)) + p2 = p1; + luaG_runerror(L, "number%s has no integer representation", varinfo(L, p2)); +} + + +l_noret luaG_ordererror (lua_State *L, const TValue *p1, const TValue *p2) { + const char *t1 = luaT_objtypename(L, p1); + const char *t2 = luaT_objtypename(L, p2); + if (strcmp(t1, t2) == 0) + luaG_runerror(L, "attempt to compare two %s values", t1); + else + luaG_runerror(L, "attempt to compare %s with %s", t1, t2); +} + + +/* add src:line information to 'msg' */ +const char *luaG_addinfo (lua_State *L, const char *msg, TString *src, + int line) { + char buff[LUA_IDSIZE]; + if (src) + luaO_chunkid(buff, getstr(src), LUA_IDSIZE); + else { /* no source available; use "?" instead */ + buff[0] = '?'; buff[1] = '\0'; + } + return luaO_pushfstring(L, "%s:%d: %s", buff, line, msg); +} + + +l_noret luaG_errormsg (lua_State *L) { + if (L->errfunc != 0) { /* is there an error handling function? */ + StkId errfunc = restorestack(L, L->errfunc); + setobjs2s(L, L->top, L->top - 1); /* move argument */ + setobjs2s(L, L->top - 1, errfunc); /* push function */ + L->top++; /* assume EXTRA_STACK */ + luaD_callnoyield(L, L->top - 2, 1); /* call it */ + } + luaD_throw(L, LUA_ERRRUN); +} + + +l_noret luaG_runerror (lua_State *L, const char *fmt, ...) { + CallInfo *ci = L->ci; + const char *msg; + va_list argp; + luaC_checkGC(L); /* error message uses memory */ + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); /* format message */ + va_end(argp); + if (isLua(ci)) /* if Lua function, add source:line information */ + luaG_addinfo(L, msg, ci_func(ci)->p->source, currentline(ci)); + luaG_errormsg(L); +} + + +void luaG_traceexec (lua_State *L) { + CallInfo *ci = L->ci; + lu_byte mask = L->hookmask; + int counthook = (--L->hookcount == 0 && (mask & LUA_MASKCOUNT)); + if (counthook) + resethookcount(L); /* reset count */ + else if (!(mask & LUA_MASKLINE)) + return; /* no line hook and count != 0; nothing to be done */ + if (ci->callstatus & CIST_HOOKYIELD) { /* called hook last time? */ + ci->callstatus &= ~CIST_HOOKYIELD; /* erase mark */ + return; /* do not call hook again (VM yielded, so it did not move) */ + } + if (counthook) + luaD_hook(L, LUA_HOOKCOUNT, -1); /* call count hook */ + if (mask & LUA_MASKLINE) { + Proto *p = ci_func(ci)->p; + int npc = pcRel(ci->u.l.savedpc, p); + int newline = getfuncline(p, npc); + if (npc == 0 || /* call linehook when enter a new function, */ + ci->u.l.savedpc <= L->oldpc || /* when jump back (loop), or when */ + newline != getfuncline(p, pcRel(L->oldpc, p))) /* enter a new line */ + luaD_hook(L, LUA_HOOKLINE, newline); /* call line hook */ + } + L->oldpc = ci->u.l.savedpc; + if (L->status == LUA_YIELD) { /* did hook yield? */ + if (counthook) + L->hookcount = 1; /* undo decrement to zero */ + ci->u.l.savedpc--; /* undo increment (resume will increment it again) */ + ci->callstatus |= CIST_HOOKYIELD; /* mark that it yielded */ + ci->func = L->top - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } +} + diff --git a/src/lua/ldebug.h b/src/lua/ldebug.h new file mode 100644 index 000000000000..8cea0ee0a72c --- /dev/null +++ b/src/lua/ldebug.h @@ -0,0 +1,39 @@ +/* +** $Id: ldebug.h,v 2.14.1.1 2017/04/19 17:20:42 roberto Exp $ +** Auxiliary functions from Debug Interface module +** See Copyright Notice in lua.h +*/ + +#ifndef ldebug_h +#define ldebug_h + + +#include "lstate.h" + + +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) + +#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : -1) + +#define resethookcount(L) (L->hookcount = L->basehookcount) + + +LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, + const char *opname); +LUAI_FUNC l_noret luaG_concaterror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_opinterror (lua_State *L, const TValue *p1, + const TValue *p2, + const char *msg); +LUAI_FUNC l_noret luaG_tointerror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_ordererror (lua_State *L, const TValue *p1, + const TValue *p2); +LUAI_FUNC l_noret luaG_runerror (lua_State *L, const char *fmt, ...); +LUAI_FUNC const char *luaG_addinfo (lua_State *L, const char *msg, + TString *src, int line); +LUAI_FUNC l_noret luaG_errormsg (lua_State *L); +LUAI_FUNC void luaG_traceexec (lua_State *L); + + +#endif diff --git a/src/lua/ldo.c b/src/lua/ldo.c new file mode 100644 index 000000000000..316e45c8fec5 --- /dev/null +++ b/src/lua/ldo.c @@ -0,0 +1,802 @@ +/* +** $Id: ldo.c,v 2.157.1.1 2017/04/19 17:20:42 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#define ldo_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lundump.h" +#include "lvm.h" +#include "lzio.h" + + + +#define errorstatus(s) ((s) > LUA_YIELD) + + +/* +** {====================================================== +** Error-recovery functions +** ======================================================= +*/ + +/* +** LUAI_THROW/LUAI_TRY define how Lua does exception handling. By +** default, Lua handles errors with exceptions when compiling as +** C++ code, with _longjmp/_setjmp when asked to use them, and with +** longjmp/setjmp otherwise. +*/ +#if !defined(LUAI_THROW) /* { */ + +#if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* { */ + +/* C++ exceptions */ +#define LUAI_THROW(L,c) throw(c) +#define LUAI_TRY(L,c,a) \ + try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ + +#elif defined(LUA_USE_POSIX) /* }{ */ + +/* in POSIX, try _longjmp/_setjmp (more efficient) */ +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#else /* }{ */ + +/* ISO C handling with long jumps */ +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf + +#endif /* } */ + +#endif /* } */ + + + +/* chain list of long jump buffers */ +struct lua_longjmp { + struct lua_longjmp *previous; + luai_jmpbuf b; + volatile int status; /* error code */ +}; + + +static void seterrorobj (lua_State *L, int errcode, StkId oldtop) { + switch (errcode) { + case LUA_ERRMEM: { /* memory error? */ + setsvalue2s(L, oldtop, G(L)->memerrmsg); /* reuse preregistered msg. */ + break; + } + case LUA_ERRERR: { + setsvalue2s(L, oldtop, luaS_newliteral(L, "error in error handling")); + break; + } + default: { + setobjs2s(L, oldtop, L->top - 1); /* error message on current top */ + break; + } + } + L->top = oldtop + 1; +} + + +l_noret luaD_throw (lua_State *L, int errcode) { + if (L->errorJmp) { /* thread has an error handler? */ + L->errorJmp->status = errcode; /* set status */ + LUAI_THROW(L, L->errorJmp); /* jump to it */ + } + else { /* thread has no error handler */ + global_State *g = G(L); + L->status = cast_byte(errcode); /* mark it as dead */ + if (g->mainthread->errorJmp) { /* main thread has a handler? */ + setobjs2s(L, g->mainthread->top++, L->top - 1); /* copy error obj. */ + luaD_throw(g->mainthread, errcode); /* re-throw in main thread */ + } + else { /* no handler at all; abort */ + if (g->panic) { /* panic function? */ + seterrorobj(L, errcode, L->top); /* assume EXTRA_STACK */ + if (L->ci->top < L->top) + L->ci->top = L->top; /* pushing msg. can break this invariant */ + lua_unlock(L); + g->panic(L); /* call panic function (last chance to jump out) */ + } + abort(); + } + } +} + + +int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud) { + unsigned short oldnCcalls = L->nCcalls; + struct lua_longjmp lj; + lj.status = LUA_OK; + lj.previous = L->errorJmp; /* chain new error handler */ + L->errorJmp = &lj; + LUAI_TRY(L, &lj, + (*f)(L, ud); + ); + L->errorJmp = lj.previous; /* restore old error handler */ + L->nCcalls = oldnCcalls; + return lj.status; +} + +/* }====================================================== */ + + +/* +** {================================================================== +** Stack reallocation +** =================================================================== +*/ +static void correctstack (lua_State *L, TValue *oldstack) { + CallInfo *ci; + UpVal *up; + L->top = (L->top - oldstack) + L->stack; + for (up = L->openupval; up != NULL; up = up->u.open.next) + up->v = (up->v - oldstack) + L->stack; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + ci->top = (ci->top - oldstack) + L->stack; + ci->func = (ci->func - oldstack) + L->stack; + if (isLua(ci)) + ci->u.l.base = (ci->u.l.base - oldstack) + L->stack; + } +} + + +/* some space for error handling */ +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) + + +void luaD_reallocstack (lua_State *L, int newsize) { + TValue *oldstack = L->stack; + int lim = L->stacksize; + lua_assert(newsize <= LUAI_MAXSTACK || newsize == ERRORSTACKSIZE); + lua_assert(L->stack_last - L->stack == L->stacksize - EXTRA_STACK); + luaM_reallocvector(L, L->stack, L->stacksize, newsize, TValue); + for (; lim < newsize; lim++) + setnilvalue(L->stack + lim); /* erase new segment */ + L->stacksize = newsize; + L->stack_last = L->stack + newsize - EXTRA_STACK; + correctstack(L, oldstack); +} + + +void luaD_growstack (lua_State *L, int n) { + int size = L->stacksize; + if (size > LUAI_MAXSTACK) /* error after extra size? */ + luaD_throw(L, LUA_ERRERR); + else { + int needed = cast_int(L->top - L->stack) + n + EXTRA_STACK; + int newsize = 2 * size; + if (newsize > LUAI_MAXSTACK) newsize = LUAI_MAXSTACK; + if (newsize < needed) newsize = needed; + if (newsize > LUAI_MAXSTACK) { /* stack overflow? */ + luaD_reallocstack(L, ERRORSTACKSIZE); + luaG_runerror(L, "stack overflow"); + } + else + luaD_reallocstack(L, newsize); + } +} + + +static int stackinuse (lua_State *L) { + CallInfo *ci; + StkId lim = L->top; + for (ci = L->ci; ci != NULL; ci = ci->previous) { + if (lim < ci->top) lim = ci->top; + } + lua_assert(lim <= L->stack_last); + return cast_int(lim - L->stack) + 1; /* part of stack in use */ +} + + +void luaD_shrinkstack (lua_State *L) { + int inuse = stackinuse(L); + int goodsize = inuse + (inuse / 8) + 2*EXTRA_STACK; + if (goodsize > LUAI_MAXSTACK) + goodsize = LUAI_MAXSTACK; /* respect stack limit */ + if (L->stacksize > LUAI_MAXSTACK) /* had been handling stack overflow? */ + luaE_freeCI(L); /* free all CIs (list grew because of an error) */ + else + luaE_shrinkCI(L); /* shrink list */ + /* if thread is currently not handling a stack overflow and its + good size is smaller than current size, shrink its stack */ + if (inuse <= (LUAI_MAXSTACK - EXTRA_STACK) && + goodsize < L->stacksize) + luaD_reallocstack(L, goodsize); + else /* don't change stack */ + condmovestack(L,{},{}); /* (change only for debugging) */ +} + + +void luaD_inctop (lua_State *L) { + luaD_checkstack(L, 1); + L->top++; +} + +/* }================================================================== */ + + +/* +** Call a hook for the given event. Make sure there is a hook to be +** called. (Both 'L->hook' and 'L->hookmask', which triggers this +** function, can be changed asynchronously by signals.) +*/ +void luaD_hook (lua_State *L, int event, int line) { + lua_Hook hook = L->hook; + if (hook && L->allowhook) { /* make sure there is a hook */ + CallInfo *ci = L->ci; + ptrdiff_t top = savestack(L, L->top); + ptrdiff_t ci_top = savestack(L, ci->top); + lua_Debug ar; + ar.event = event; + ar.currentline = line; + ar.i_ci = ci; + luaD_checkstack(L, LUA_MINSTACK); /* ensure minimum stack size */ + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + L->allowhook = 0; /* cannot call hooks inside a hook */ + ci->callstatus |= CIST_HOOKED; + lua_unlock(L); + (*hook)(L, &ar); + lua_lock(L); + lua_assert(!L->allowhook); + L->allowhook = 1; + ci->top = restorestack(L, ci_top); + L->top = restorestack(L, top); + ci->callstatus &= ~CIST_HOOKED; + } +} + + +static void callhook (lua_State *L, CallInfo *ci) { + int hook = LUA_HOOKCALL; + ci->u.l.savedpc++; /* hooks assume 'pc' is already incremented */ + if (isLua(ci->previous) && + GET_OPCODE(*(ci->previous->u.l.savedpc - 1)) == OP_TAILCALL) { + ci->callstatus |= CIST_TAIL; + hook = LUA_HOOKTAILCALL; + } + luaD_hook(L, hook, -1); + ci->u.l.savedpc--; /* correct 'pc' */ +} + + +static StkId adjust_varargs (lua_State *L, Proto *p, int actual) { + int i; + int nfixargs = p->numparams; + StkId base, fixed; + /* move fixed parameters to final position */ + fixed = L->top - actual; /* first fixed argument */ + base = L->top; /* final position of first argument */ + for (i = 0; i < nfixargs && i < actual; i++) { + setobjs2s(L, L->top++, fixed + i); + setnilvalue(fixed + i); /* erase original copy (for GC) */ + } + for (; i < nfixargs; i++) + setnilvalue(L->top++); /* complete missing arguments */ + return base; +} + + +/* +** Check whether __call metafield of 'func' is a function. If so, put +** it in stack below original 'func' so that 'luaD_precall' can call +** it. Raise an error if __call metafield is not a function. +*/ +static void tryfuncTM (lua_State *L, StkId func) { + const TValue *tm = luaT_gettmbyobj(L, func, TM_CALL); + StkId p; + if (!ttisfunction(tm)) + luaG_typeerror(L, func, "call"); + /* Open a hole inside the stack at 'func' */ + for (p = L->top; p > func; p--) + setobjs2s(L, p, p-1); + L->top++; /* slot ensured by caller */ + setobj2s(L, func, tm); /* tag method is the new function to be called */ +} + + +/* +** Given 'nres' results at 'firstResult', move 'wanted' of them to 'res'. +** Handle most typical cases (zero results for commands, one result for +** expressions, multiple results for tail calls/single parameters) +** separated. +*/ +static int moveresults (lua_State *L, const TValue *firstResult, StkId res, + int nres, int wanted) { + switch (wanted) { /* handle typical cases separately */ + case 0: break; /* nothing to move */ + case 1: { /* one result needed */ + if (nres == 0) /* no results? */ + firstResult = luaO_nilobject; /* adjust with nil */ + setobjs2s(L, res, firstResult); /* move it to proper place */ + break; + } + case LUA_MULTRET: { + int i; + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + L->top = res + nres; + return 0; /* wanted == LUA_MULTRET */ + } + default: { + int i; + if (wanted <= nres) { /* enough results? */ + for (i = 0; i < wanted; i++) /* move wanted results to correct place */ + setobjs2s(L, res + i, firstResult + i); + } + else { /* not enough results; use all of them plus nils */ + for (i = 0; i < nres; i++) /* move all results to correct place */ + setobjs2s(L, res + i, firstResult + i); + for (; i < wanted; i++) /* complete wanted number of results */ + setnilvalue(res + i); + } + break; + } + } + L->top = res + wanted; /* top points after the last result */ + return 1; +} + + +/* +** Finishes a function call: calls hook if necessary, removes CallInfo, +** moves current number of results to proper place; returns 0 iff call +** wanted multiple (variable number of) results. +*/ +int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, int nres) { + StkId res; + int wanted = ci->nresults; + if (L->hookmask & (LUA_MASKRET | LUA_MASKLINE)) { + if (L->hookmask & LUA_MASKRET) { + ptrdiff_t fr = savestack(L, firstResult); /* hook may change stack */ + luaD_hook(L, LUA_HOOKRET, -1); + firstResult = restorestack(L, fr); + } + L->oldpc = ci->previous->u.l.savedpc; /* 'oldpc' for caller function */ + } + res = ci->func; /* res == final position of 1st result */ + L->ci = ci->previous; /* back to caller */ + /* move results to proper place */ + return moveresults(L, firstResult, res, nres, wanted); +} + + + +#define next_ci(L) (L->ci = (L->ci->next ? L->ci->next : luaE_extendCI(L))) + + +/* macro to check stack size, preserving 'p' */ +#define checkstackp(L,n,p) \ + luaD_checkstackaux(L, n, \ + ptrdiff_t t__ = savestack(L, p); /* save 'p' */ \ + luaC_checkGC(L), /* stack grow uses memory */ \ + p = restorestack(L, t__)) /* 'pos' part: restore 'p' */ + + +/* +** Prepares a function call: checks the stack, creates a new CallInfo +** entry, fills in the relevant information, calls hook if needed. +** If function is a C function, does the call, too. (Otherwise, leave +** the execution ('luaV_execute') to the caller, to allow stackless +** calls.) Returns true iff function has been executed (C function). +*/ +int luaD_precall (lua_State *L, StkId func, int nresults) { + lua_CFunction f; + CallInfo *ci; + switch (ttype(func)) { + case LUA_TCCL: /* C closure */ + f = clCvalue(func)->f; + goto Cfunc; + case LUA_TLCF: /* light C function */ + f = fvalue(func); + Cfunc: { + int n; /* number of returns */ + checkstackp(L, LUA_MINSTACK, func); /* ensure minimum stack size */ + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->top = L->top + LUA_MINSTACK; + lua_assert(ci->top <= L->stack_last); + ci->callstatus = 0; + if (L->hookmask & LUA_MASKCALL) + luaD_hook(L, LUA_HOOKCALL, -1); + lua_unlock(L); + n = (*f)(L); /* do the actual call */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, L->top - n, n); + return 1; + } + case LUA_TLCL: { /* Lua function: prepare its call */ + StkId base; + Proto *p = clLvalue(func)->p; + int n = cast_int(L->top - func) - 1; /* number of real arguments */ + int fsize = p->maxstacksize; /* frame size */ + checkstackp(L, fsize, func); + if (p->is_vararg) + base = adjust_varargs(L, p, n); + else { /* non vararg function */ + for (; n < p->numparams; n++) + setnilvalue(L->top++); /* complete missing arguments */ + base = func + 1; + } + ci = next_ci(L); /* now 'enter' new function */ + ci->nresults = nresults; + ci->func = func; + ci->u.l.base = base; + L->top = ci->top = base + fsize; + lua_assert(ci->top <= L->stack_last); + ci->u.l.savedpc = p->code; /* starting point */ + ci->callstatus = CIST_LUA; + if (L->hookmask & LUA_MASKCALL) + callhook(L, ci); + return 0; + } + default: { /* not a function */ + checkstackp(L, 1, func); /* ensure space for metamethod */ + tryfuncTM(L, func); /* try to get '__call' metamethod */ + return luaD_precall(L, func, nresults); /* now it must be a function */ + } + } +} + + +/* +** Check appropriate error for stack overflow ("regular" overflow or +** overflow while handling stack overflow). If 'nCalls' is larger than +** LUAI_MAXCCALLS (which means it is handling a "regular" overflow) but +** smaller than 9/8 of LUAI_MAXCCALLS, does not report an error (to +** allow overflow handling to work) +*/ +static void stackerror (lua_State *L) { + if (L->nCcalls == LUAI_MAXCCALLS) + luaG_runerror(L, "C stack overflow"); + else if (L->nCcalls >= (LUAI_MAXCCALLS + (LUAI_MAXCCALLS>>3))) + luaD_throw(L, LUA_ERRERR); /* error while handing stack error */ +} + + +/* +** Call a function (C or Lua). The function to be called is at *func. +** The arguments are on the stack, right after the function. +** When returns, all the results are on the stack, starting at the original +** function position. +*/ +void luaD_call (lua_State *L, StkId func, int nResults) { + if (++L->nCcalls >= LUAI_MAXCCALLS) + stackerror(L); + if (!luaD_precall(L, func, nResults)) /* is a Lua function? */ + luaV_execute(L); /* call it */ + L->nCcalls--; +} + + +/* +** Similar to 'luaD_call', but does not allow yields during the call +*/ +void luaD_callnoyield (lua_State *L, StkId func, int nResults) { + L->nny++; + luaD_call(L, func, nResults); + L->nny--; +} + + +/* +** Completes the execution of an interrupted C function, calling its +** continuation function. +*/ +static void finishCcall (lua_State *L, int status) { + CallInfo *ci = L->ci; + int n; + /* must have a continuation and must be able to call it */ + lua_assert(ci->u.c.k != NULL && L->nny == 0); + /* error status can only happen in a protected call */ + lua_assert((ci->callstatus & CIST_YPCALL) || status == LUA_YIELD); + if (ci->callstatus & CIST_YPCALL) { /* was inside a pcall? */ + ci->callstatus &= ~CIST_YPCALL; /* continuation is also inside it */ + L->errfunc = ci->u.c.old_errfunc; /* with the same error function */ + } + /* finish 'lua_callk'/'lua_pcall'; CIST_YPCALL and 'errfunc' already + handled */ + adjustresults(L, ci->nresults); + lua_unlock(L); + n = (*ci->u.c.k)(L, status, ci->u.c.ctx); /* call continuation function */ + lua_lock(L); + api_checknelems(L, n); + luaD_poscall(L, ci, L->top - n, n); /* finish 'luaD_precall' */ +} + + +/* +** Executes "full continuation" (everything in the stack) of a +** previously interrupted coroutine until the stack is empty (or another +** interruption long-jumps out of the loop). If the coroutine is +** recovering from an error, 'ud' points to the error status, which must +** be passed to the first continuation function (otherwise the default +** status is LUA_YIELD). +*/ +static void unroll (lua_State *L, void *ud) { + if (ud != NULL) /* error status? */ + finishCcall(L, *(int *)ud); /* finish 'lua_pcallk' callee */ + while (L->ci != &L->base_ci) { /* something in the stack */ + if (!isLua(L->ci)) /* C function? */ + finishCcall(L, LUA_YIELD); /* complete its execution */ + else { /* Lua function */ + luaV_finishOp(L); /* finish interrupted instruction */ + luaV_execute(L); /* execute down to higher C 'boundary' */ + } + } +} + + +/* +** Try to find a suspended protected call (a "recover point") for the +** given thread. +*/ +static CallInfo *findpcall (lua_State *L) { + CallInfo *ci; + for (ci = L->ci; ci != NULL; ci = ci->previous) { /* search for a pcall */ + if (ci->callstatus & CIST_YPCALL) + return ci; + } + return NULL; /* no pending pcall */ +} + + +/* +** Recovers from an error in a coroutine. Finds a recover point (if +** there is one) and completes the execution of the interrupted +** 'luaD_pcall'. If there is no recover point, returns zero. +*/ +static int recover (lua_State *L, int status) { + StkId oldtop; + CallInfo *ci = findpcall(L); + if (ci == NULL) return 0; /* no recovery point */ + /* "finish" luaD_pcall */ + oldtop = restorestack(L, ci->extra); + luaF_close(L, oldtop); + seterrorobj(L, status, oldtop); + L->ci = ci; + L->allowhook = getoah(ci->callstatus); /* restore original 'allowhook' */ + L->nny = 0; /* should be zero to be yieldable */ + luaD_shrinkstack(L); + L->errfunc = ci->u.c.old_errfunc; + return 1; /* continue running the coroutine */ +} + + +/* +** Signal an error in the call to 'lua_resume', not in the execution +** of the coroutine itself. (Such errors should not be handled by any +** coroutine error handler and should not kill the coroutine.) +*/ +static int resume_error (lua_State *L, const char *msg, int narg) { + L->top -= narg; /* remove args from the stack */ + setsvalue2s(L, L->top, luaS_new(L, msg)); /* push error message */ + api_incr_top(L); + lua_unlock(L); + return LUA_ERRRUN; +} + + +/* +** Do the work for 'lua_resume' in protected mode. Most of the work +** depends on the status of the coroutine: initial state, suspended +** inside a hook, or regularly suspended (optionally with a continuation +** function), plus erroneous cases: non-suspended coroutine or dead +** coroutine. +*/ +static void resume (lua_State *L, void *ud) { + int n = *(cast(int*, ud)); /* number of arguments */ + StkId firstArg = L->top - n; /* first argument */ + CallInfo *ci = L->ci; + if (L->status == LUA_OK) { /* starting a coroutine? */ + if (!luaD_precall(L, firstArg - 1, LUA_MULTRET)) /* Lua function? */ + luaV_execute(L); /* call it */ + } + else { /* resuming from previous yield */ + lua_assert(L->status == LUA_YIELD); + L->status = LUA_OK; /* mark that it is running (again) */ + ci->func = restorestack(L, ci->extra); + if (isLua(ci)) /* yielded inside a hook? */ + luaV_execute(L); /* just continue running Lua code */ + else { /* 'common' yield */ + if (ci->u.c.k != NULL) { /* does it have a continuation function? */ + lua_unlock(L); + n = (*ci->u.c.k)(L, LUA_YIELD, ci->u.c.ctx); /* call continuation */ + lua_lock(L); + api_checknelems(L, n); + firstArg = L->top - n; /* yield results come from continuation */ + } + luaD_poscall(L, ci, firstArg, n); /* finish 'luaD_precall' */ + } + unroll(L, NULL); /* run continuation */ + } +} + + +LUA_API int lua_resume (lua_State *L, lua_State *from, int nargs) { + int status; + unsigned short oldnny = L->nny; /* save "number of non-yieldable" calls */ + lua_lock(L); + if (L->status == LUA_OK) { /* may be starting a coroutine */ + if (L->ci != &L->base_ci) /* not in base level? */ + return resume_error(L, "cannot resume non-suspended coroutine", nargs); + } + else if (L->status != LUA_YIELD) + return resume_error(L, "cannot resume dead coroutine", nargs); + L->nCcalls = (from) ? from->nCcalls + 1 : 1; + if (L->nCcalls >= LUAI_MAXCCALLS) + return resume_error(L, "C stack overflow", nargs); + luai_userstateresume(L, nargs); + L->nny = 0; /* allow yields */ + api_checknelems(L, (L->status == LUA_OK) ? nargs + 1 : nargs); + status = luaD_rawrunprotected(L, resume, &nargs); + if (status == -1) /* error calling 'lua_resume'? */ + status = LUA_ERRRUN; + else { /* continue running after recoverable errors */ + while (errorstatus(status) && recover(L, status)) { + /* unroll continuation */ + status = luaD_rawrunprotected(L, unroll, &status); + } + if (errorstatus(status)) { /* unrecoverable error? */ + L->status = cast_byte(status); /* mark thread as 'dead' */ + seterrorobj(L, status, L->top); /* push error message */ + L->ci->top = L->top; + } + else lua_assert(status == L->status); /* normal end or yield */ + } + L->nny = oldnny; /* restore 'nny' */ + L->nCcalls--; + lua_assert(L->nCcalls == ((from) ? from->nCcalls : 0)); + lua_unlock(L); + return status; +} + + +LUA_API int lua_isyieldable (lua_State *L) { + return (L->nny == 0); +} + + +LUA_API int lua_yieldk (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k) { + CallInfo *ci = L->ci; + luai_userstateyield(L, nresults); + lua_lock(L); + api_checknelems(L, nresults); + if (L->nny > 0) { + if (L != G(L)->mainthread) + luaG_runerror(L, "attempt to yield across a C-call boundary"); + else + luaG_runerror(L, "attempt to yield from outside a coroutine"); + } + L->status = LUA_YIELD; + ci->extra = savestack(L, ci->func); /* save current 'func' */ + if (isLua(ci)) { /* inside a hook? */ + api_check(L, k == NULL, "hooks cannot continue after yielding"); + } + else { + if ((ci->u.c.k = k) != NULL) /* is there a continuation? */ + ci->u.c.ctx = ctx; /* save context */ + ci->func = L->top - nresults - 1; /* protect stack below results */ + luaD_throw(L, LUA_YIELD); + } + lua_assert(ci->callstatus & CIST_HOOKED); /* must be inside a hook */ + lua_unlock(L); + return 0; /* return to 'luaD_hook' */ +} + + +int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t old_top, ptrdiff_t ef) { + int status; + CallInfo *old_ci = L->ci; + lu_byte old_allowhooks = L->allowhook; + unsigned short old_nny = L->nny; + ptrdiff_t old_errfunc = L->errfunc; + L->errfunc = ef; + status = luaD_rawrunprotected(L, func, u); + if (status != LUA_OK) { /* an error occurred? */ + StkId oldtop = restorestack(L, old_top); + luaF_close(L, oldtop); /* close possible pending closures */ + seterrorobj(L, status, oldtop); + L->ci = old_ci; + L->allowhook = old_allowhooks; + L->nny = old_nny; + luaD_shrinkstack(L); + } + L->errfunc = old_errfunc; + return status; +} + + + +/* +** Execute a protected parser. +*/ +struct SParser { /* data to 'f_parser' */ + ZIO *z; + Mbuffer buff; /* dynamic structure used by the scanner */ + Dyndata dyd; /* dynamic structures used by the parser */ + const char *mode; + const char *name; +}; + + +static void checkmode (lua_State *L, const char *mode, const char *x) { + if (mode && strchr(mode, x[0]) == NULL) { + luaO_pushfstring(L, + "attempt to load a %s chunk (mode is '%s')", x, mode); + luaD_throw(L, LUA_ERRSYNTAX); + } +} + + +static void f_parser (lua_State *L, void *ud) { + LClosure *cl; + struct SParser *p = cast(struct SParser *, ud); + int c = zgetc(p->z); /* read first character */ + if (c == LUA_SIGNATURE[0]) { + checkmode(L, p->mode, "binary"); + cl = luaU_undump(L, p->z, p->name); + } + else { + checkmode(L, p->mode, "text"); + cl = luaY_parser(L, p->z, &p->buff, &p->dyd, p->name, c); + } + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luaF_initupvals(L, cl); +} + + +int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode) { + struct SParser p; + int status; + L->nny++; /* cannot yield during parsing */ + p.z = z; p.name = name; p.mode = mode; + p.dyd.actvar.arr = NULL; p.dyd.actvar.size = 0; + p.dyd.gt.arr = NULL; p.dyd.gt.size = 0; + p.dyd.label.arr = NULL; p.dyd.label.size = 0; + luaZ_initbuffer(L, &p.buff); + status = luaD_pcall(L, f_parser, &p, savestack(L, L->top), L->errfunc); + luaZ_freebuffer(L, &p.buff); + luaM_freearray(L, p.dyd.actvar.arr, p.dyd.actvar.size); + luaM_freearray(L, p.dyd.gt.arr, p.dyd.gt.size); + luaM_freearray(L, p.dyd.label.arr, p.dyd.label.size); + L->nny--; + return status; +} + + diff --git a/src/lua/ldo.h b/src/lua/ldo.h new file mode 100644 index 000000000000..3b2983a38645 --- /dev/null +++ b/src/lua/ldo.h @@ -0,0 +1,58 @@ +/* +** $Id: ldo.h,v 2.29.1.1 2017/04/19 17:20:42 roberto Exp $ +** Stack and Call structure of Lua +** See Copyright Notice in lua.h +*/ + +#ifndef ldo_h +#define ldo_h + + +#include "lobject.h" +#include "lstate.h" +#include "lzio.h" + + +/* +** Macro to check stack size and grow stack if needed. Parameters +** 'pre'/'pos' allow the macro to preserve a pointer into the +** stack across reallocations, doing the work only when needed. +** 'condmovestack' is used in heavy tests to force a stack reallocation +** at every check. +*/ +#define luaD_checkstackaux(L,n,pre,pos) \ + if (L->stack_last - L->top <= (n)) \ + { pre; luaD_growstack(L, n); pos; } else { condmovestack(L,pre,pos); } + +/* In general, 'pre'/'pos' are empty (nothing to save) */ +#define luaD_checkstack(L,n) luaD_checkstackaux(L,n,(void)0,(void)0) + + + +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) + + +/* type of protected functions, to be ran by 'runprotected' */ +typedef void (*Pfunc) (lua_State *L, void *ud); + +LUAI_FUNC int luaD_protectedparser (lua_State *L, ZIO *z, const char *name, + const char *mode); +LUAI_FUNC void luaD_hook (lua_State *L, int event, int line); +LUAI_FUNC int luaD_precall (lua_State *L, StkId func, int nresults); +LUAI_FUNC void luaD_call (lua_State *L, StkId func, int nResults); +LUAI_FUNC void luaD_callnoyield (lua_State *L, StkId func, int nResults); +LUAI_FUNC int luaD_pcall (lua_State *L, Pfunc func, void *u, + ptrdiff_t oldtop, ptrdiff_t ef); +LUAI_FUNC int luaD_poscall (lua_State *L, CallInfo *ci, StkId firstResult, + int nres); +LUAI_FUNC void luaD_reallocstack (lua_State *L, int newsize); +LUAI_FUNC void luaD_growstack (lua_State *L, int n); +LUAI_FUNC void luaD_shrinkstack (lua_State *L); +LUAI_FUNC void luaD_inctop (lua_State *L); + +LUAI_FUNC l_noret luaD_throw (lua_State *L, int errcode); +LUAI_FUNC int luaD_rawrunprotected (lua_State *L, Pfunc f, void *ud); + +#endif + diff --git a/src/lua/ldump.c b/src/lua/ldump.c new file mode 100644 index 000000000000..f025acac3c23 --- /dev/null +++ b/src/lua/ldump.c @@ -0,0 +1,215 @@ +/* +** $Id: ldump.c,v 2.37.1.1 2017/04/19 17:20:42 roberto Exp $ +** save precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define ldump_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lobject.h" +#include "lstate.h" +#include "lundump.h" + + +typedef struct { + lua_State *L; + lua_Writer writer; + void *data; + int strip; + int status; +} DumpState; + + +/* +** All high-level dumps go through DumpVector; you can change it to +** change the endianness of the result +*/ +#define DumpVector(v,n,D) DumpBlock(v,(n)*sizeof((v)[0]),D) + +#define DumpLiteral(s,D) DumpBlock(s, sizeof(s) - sizeof(char), D) + + +static void DumpBlock (const void *b, size_t size, DumpState *D) { + if (D->status == 0 && size > 0) { + lua_unlock(D->L); + D->status = (*D->writer)(D->L, b, size, D->data); + lua_lock(D->L); + } +} + + +#define DumpVar(x,D) DumpVector(&x,1,D) + + +static void DumpByte (int y, DumpState *D) { + lu_byte x = (lu_byte)y; + DumpVar(x, D); +} + + +static void DumpInt (int x, DumpState *D) { + DumpVar(x, D); +} + + +static void DumpNumber (lua_Number x, DumpState *D) { + DumpVar(x, D); +} + + +static void DumpInteger (lua_Integer x, DumpState *D) { + DumpVar(x, D); +} + + +static void DumpString (const TString *s, DumpState *D) { + if (s == NULL) + DumpByte(0, D); + else { + size_t size = tsslen(s) + 1; /* include trailing '\0' */ + const char *str = getstr(s); + if (size < 0xFF) + DumpByte(cast_int(size), D); + else { + DumpByte(0xFF, D); + DumpVar(size, D); + } + DumpVector(str, size - 1, D); /* no need to save '\0' */ + } +} + + +static void DumpCode (const Proto *f, DumpState *D) { + DumpInt(f->sizecode, D); + DumpVector(f->code, f->sizecode, D); +} + + +static void DumpFunction(const Proto *f, TString *psource, DumpState *D); + +static void DumpConstants (const Proto *f, DumpState *D) { + int i; + int n = f->sizek; + DumpInt(n, D); + for (i = 0; i < n; i++) { + const TValue *o = &f->k[i]; + DumpByte(ttype(o), D); + switch (ttype(o)) { + case LUA_TNIL: + break; + case LUA_TBOOLEAN: + DumpByte(bvalue(o), D); + break; + case LUA_TNUMFLT: + DumpNumber(fltvalue(o), D); + break; + case LUA_TNUMINT: + DumpInteger(ivalue(o), D); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + DumpString(tsvalue(o), D); + break; + default: + lua_assert(0); + } + } +} + + +static void DumpProtos (const Proto *f, DumpState *D) { + int i; + int n = f->sizep; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpFunction(f->p[i], f->source, D); +} + + +static void DumpUpvalues (const Proto *f, DumpState *D) { + int i, n = f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpByte(f->upvalues[i].instack, D); + DumpByte(f->upvalues[i].idx, D); + } +} + + +static void DumpDebug (const Proto *f, DumpState *D) { + int i, n; + n = (D->strip) ? 0 : f->sizelineinfo; + DumpInt(n, D); + DumpVector(f->lineinfo, n, D); + n = (D->strip) ? 0 : f->sizelocvars; + DumpInt(n, D); + for (i = 0; i < n; i++) { + DumpString(f->locvars[i].varname, D); + DumpInt(f->locvars[i].startpc, D); + DumpInt(f->locvars[i].endpc, D); + } + n = (D->strip) ? 0 : f->sizeupvalues; + DumpInt(n, D); + for (i = 0; i < n; i++) + DumpString(f->upvalues[i].name, D); +} + + +static void DumpFunction (const Proto *f, TString *psource, DumpState *D) { + if (D->strip || f->source == psource) + DumpString(NULL, D); /* no debug info or same source as its parent */ + else + DumpString(f->source, D); + DumpInt(f->linedefined, D); + DumpInt(f->lastlinedefined, D); + DumpByte(f->numparams, D); + DumpByte(f->is_vararg, D); + DumpByte(f->maxstacksize, D); + DumpCode(f, D); + DumpConstants(f, D); + DumpUpvalues(f, D); + DumpProtos(f, D); + DumpDebug(f, D); +} + + +static void DumpHeader (DumpState *D) { + DumpLiteral(LUA_SIGNATURE, D); + DumpByte(LUAC_VERSION, D); + DumpByte(LUAC_FORMAT, D); + DumpLiteral(LUAC_DATA, D); + DumpByte(sizeof(int), D); + DumpByte(sizeof(size_t), D); + DumpByte(sizeof(Instruction), D); + DumpByte(sizeof(lua_Integer), D); + DumpByte(sizeof(lua_Number), D); + DumpInteger(LUAC_INT, D); + DumpNumber(LUAC_NUM, D); +} + + +/* +** dump Lua function as precompiled chunk +*/ +int luaU_dump(lua_State *L, const Proto *f, lua_Writer w, void *data, + int strip) { + DumpState D; + D.L = L; + D.writer = w; + D.data = data; + D.strip = strip; + D.status = 0; + DumpHeader(&D); + DumpByte(f->sizeupvalues, &D); + DumpFunction(f, NULL, &D); + return D.status; +} + diff --git a/src/lua/lfunc.c b/src/lua/lfunc.c new file mode 100644 index 000000000000..ccafbb8ab3c7 --- /dev/null +++ b/src/lua/lfunc.c @@ -0,0 +1,151 @@ +/* +** $Id: lfunc.c,v 2.45.1.1 2017/04/19 17:39:34 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#define lfunc_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +CClosure *luaF_newCclosure (lua_State *L, int n) { + GCObject *o = luaC_newobj(L, LUA_TCCL, sizeCclosure(n)); + CClosure *c = gco2ccl(o); + c->nupvalues = cast_byte(n); + return c; +} + + +LClosure *luaF_newLclosure (lua_State *L, int n) { + GCObject *o = luaC_newobj(L, LUA_TLCL, sizeLclosure(n)); + LClosure *c = gco2lcl(o); + c->p = NULL; + c->nupvalues = cast_byte(n); + while (n--) c->upvals[n] = NULL; + return c; +} + +/* +** fill a closure with new closed upvalues +*/ +void luaF_initupvals (lua_State *L, LClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) { + UpVal *uv = luaM_new(L, UpVal); + uv->refcount = 1; + uv->v = &uv->u.value; /* make it closed */ + setnilvalue(uv->v); + cl->upvals[i] = uv; + } +} + + +UpVal *luaF_findupval (lua_State *L, StkId level) { + UpVal **pp = &L->openupval; + UpVal *p; + UpVal *uv; + lua_assert(isintwups(L) || L->openupval == NULL); + while (*pp != NULL && (p = *pp)->v >= level) { + lua_assert(upisopen(p)); + if (p->v == level) /* found a corresponding upvalue? */ + return p; /* return it */ + pp = &p->u.open.next; + } + /* not found: create a new upvalue */ + uv = luaM_new(L, UpVal); + uv->refcount = 0; + uv->u.open.next = *pp; /* link it to list of open upvalues */ + uv->u.open.touched = 1; + *pp = uv; + uv->v = level; /* current value lives in the stack */ + if (!isintwups(L)) { /* thread not in list of threads with upvalues? */ + L->twups = G(L)->twups; /* link it to the list */ + G(L)->twups = L; + } + return uv; +} + + +void luaF_close (lua_State *L, StkId level) { + UpVal *uv; + while (L->openupval != NULL && (uv = L->openupval)->v >= level) { + lua_assert(upisopen(uv)); + L->openupval = uv->u.open.next; /* remove from 'open' list */ + if (uv->refcount == 0) /* no references? */ + luaM_free(L, uv); /* free upvalue */ + else { + setobj(L, &uv->u.value, uv->v); /* move value to upvalue slot */ + uv->v = &uv->u.value; /* now current value lives here */ + luaC_upvalbarrier(L, uv); + } + } +} + + +Proto *luaF_newproto (lua_State *L) { + GCObject *o = luaC_newobj(L, LUA_TPROTO, sizeof(Proto)); + Proto *f = gco2p(o); + f->k = NULL; + f->sizek = 0; + f->p = NULL; + f->sizep = 0; + f->code = NULL; + f->cache = NULL; + f->sizecode = 0; + f->lineinfo = NULL; + f->sizelineinfo = 0; + f->upvalues = NULL; + f->sizeupvalues = 0; + f->numparams = 0; + f->is_vararg = 0; + f->maxstacksize = 0; + f->locvars = NULL; + f->sizelocvars = 0; + f->linedefined = 0; + f->lastlinedefined = 0; + f->source = NULL; + return f; +} + + +void luaF_freeproto (lua_State *L, Proto *f) { + luaM_freearray(L, f->code, f->sizecode); + luaM_freearray(L, f->p, f->sizep); + luaM_freearray(L, f->k, f->sizek); + luaM_freearray(L, f->lineinfo, f->sizelineinfo); + luaM_freearray(L, f->locvars, f->sizelocvars); + luaM_freearray(L, f->upvalues, f->sizeupvalues); + luaM_free(L, f); +} + + +/* +** Look for n-th local variable at line 'line' in function 'func'. +** Returns NULL if not found. +*/ +const char *luaF_getlocalname (const Proto *f, int local_number, int pc) { + int i; + for (i = 0; isizelocvars && f->locvars[i].startpc <= pc; i++) { + if (pc < f->locvars[i].endpc) { /* is variable active? */ + local_number--; + if (local_number == 0) + return getstr(f->locvars[i].varname); + } + } + return NULL; /* not found */ +} + diff --git a/src/lua/lfunc.h b/src/lua/lfunc.h new file mode 100644 index 000000000000..c916e9878ade --- /dev/null +++ b/src/lua/lfunc.h @@ -0,0 +1,61 @@ +/* +** $Id: lfunc.h,v 2.15.1.1 2017/04/19 17:39:34 roberto Exp $ +** Auxiliary functions to manipulate prototypes and closures +** See Copyright Notice in lua.h +*/ + +#ifndef lfunc_h +#define lfunc_h + + +#include "lobject.h" + + +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ + cast(int, sizeof(TValue)*((n)-1))) + +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ + cast(int, sizeof(TValue *)*((n)-1))) + + +/* test whether thread is in 'twups' list */ +#define isintwups(L) (L->twups != L) + + +/* +** maximum number of upvalues in a closure (both C and Lua). (Value +** must fit in a VM register.) +*/ +#define MAXUPVAL 255 + + +/* +** Upvalues for Lua closures +*/ +struct UpVal { + TValue *v; /* points to stack or to its own value */ + lu_mem refcount; /* reference counter */ + union { + struct { /* (when open) */ + UpVal *next; /* linked list */ + int touched; /* mark to avoid cycles with dead threads */ + } open; + TValue value; /* the value (when closed) */ + } u; +}; + +#define upisopen(up) ((up)->v != &(up)->u.value) + + +LUAI_FUNC Proto *luaF_newproto (lua_State *L); +LUAI_FUNC CClosure *luaF_newCclosure (lua_State *L, int nelems); +LUAI_FUNC LClosure *luaF_newLclosure (lua_State *L, int nelems); +LUAI_FUNC void luaF_initupvals (lua_State *L, LClosure *cl); +LUAI_FUNC UpVal *luaF_findupval (lua_State *L, StkId level); +LUAI_FUNC void luaF_close (lua_State *L, StkId level); +LUAI_FUNC void luaF_freeproto (lua_State *L, Proto *f); +LUAI_FUNC const char *luaF_getlocalname (const Proto *func, int local_number, + int pc); + + +#endif diff --git a/src/lua/lgc.c b/src/lua/lgc.c new file mode 100644 index 000000000000..db4df82922e0 --- /dev/null +++ b/src/lua/lgc.c @@ -0,0 +1,1179 @@ +/* +** $Id: lgc.c,v 2.215.1.2 2017/08/31 16:15:27 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#define lgc_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +/* +** internal state for collector while inside the atomic phase. The +** collector should never be in this state while running regular code. +*/ +#define GCSinsideatomic (GCSpause + 1) + +/* +** cost of sweeping one element (the size of a small object divided +** by some adjust for the sweep speed) +*/ +#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) + +/* maximum number of elements to sweep in each single step */ +#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) + +/* cost of calling one finalizer */ +#define GCFINALIZECOST GCSWEEPCOST + + +/* +** macro to adjust 'stepmul': 'stepmul' is actually used like +** 'stepmul / STEPMULADJ' (value chosen by tests) +*/ +#define STEPMULADJ 200 + + +/* +** macro to adjust 'pause': 'pause' is actually used like +** 'pause / PAUSEADJ' (value chosen by tests) +*/ +#define PAUSEADJ 100 + + +/* +** 'makewhite' erases all color bits then sets only the current white +** bit +*/ +#define maskcolors (~(bitmask(BLACKBIT) | WHITEBITS)) +#define makewhite(g,x) \ + (x->marked = cast_byte((x->marked & maskcolors) | luaC_white(g))) + +#define white2gray(x) resetbits(x->marked, WHITEBITS) +#define black2gray(x) resetbit(x->marked, BLACKBIT) + + +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) + +#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) + + +#define checkconsistency(obj) \ + lua_longassert(!iscollectable(obj) || righttt(obj)) + + +#define markvalue(g,o) { checkconsistency(o); \ + if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } + +#define markobject(g,t) { if (iswhite(t)) reallymarkobject(g, obj2gco(t)); } + +/* +** mark an object that can be NULL (either because it is really optional, +** or it was stripped as debug info, or inside an uncompleted structure) +*/ +#define markobjectN(g,t) { if (t) markobject(g,t); } + +static void reallymarkobject (global_State *g, GCObject *o); + + +/* +** {====================================================== +** Generic functions +** ======================================================= +*/ + + +/* +** one after last element in a hash array +*/ +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) + + +/* +** link collectable object 'o' into list pointed by 'p' +*/ +#define linkgclist(o,p) ((o)->gclist = (p), (p) = obj2gco(o)) + + +/* +** If key is not marked, mark its entry as dead. This allows key to be +** collected, but keeps its entry in the table. A dead node is needed +** when Lua looks up for a key (it may be part of a chain) and when +** traversing a weak table (key might be removed from the table during +** traversal). Other places never manipulate dead keys, because its +** associated nil value is enough to signal that the entry is logically +** empty. +*/ +static void removeentry (Node *n) { + lua_assert(ttisnil(gval(n))); + if (valiswhite(gkey(n))) + setdeadvalue(wgkey(n)); /* unused and unmarked key; remove it */ +} + + +/* +** tells whether a key or value can be cleared from a weak +** table. Non-collectable objects are never removed from weak +** tables. Strings behave as 'values', so are never removed too. for +** other objects: if really collected, cannot keep them; for objects +** being finalized, keep them in keys, but not in values +*/ +static int iscleared (global_State *g, const TValue *o) { + if (!iscollectable(o)) return 0; + else if (ttisstring(o)) { + markobject(g, tsvalue(o)); /* strings are 'values', so are never weak */ + return 0; + } + else return iswhite(gcvalue(o)); +} + + +/* +** barrier that moves collector forward, that is, mark the white object +** being pointed by a black object. (If in sweep phase, clear the black +** object to white [sweep it] to avoid other barrier calls for this +** same object.) +*/ +void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v) { + global_State *g = G(L); + lua_assert(isblack(o) && iswhite(v) && !isdead(g, v) && !isdead(g, o)); + if (keepinvariant(g)) /* must keep invariant? */ + reallymarkobject(g, v); /* restore invariant */ + else { /* sweep phase */ + lua_assert(issweepphase(g)); + makewhite(g, o); /* mark main obj. as white to avoid other barriers */ + } +} + + +/* +** barrier that moves collector backward, that is, mark the black object +** pointing to a white object as gray again. +*/ +void luaC_barrierback_ (lua_State *L, Table *t) { + global_State *g = G(L); + lua_assert(isblack(t) && !isdead(g, t)); + black2gray(t); /* make table gray (again) */ + linkgclist(t, g->grayagain); +} + + +/* +** barrier for assignments to closed upvalues. Because upvalues are +** shared among closures, it is impossible to know the color of all +** closures pointing to it. So, we assume that the object being assigned +** must be marked. +*/ +void luaC_upvalbarrier_ (lua_State *L, UpVal *uv) { + global_State *g = G(L); + GCObject *o = gcvalue(uv->v); + lua_assert(!upisopen(uv)); /* ensured by macro luaC_upvalbarrier */ + if (keepinvariant(g)) + markobject(g, o); +} + + +void luaC_fix (lua_State *L, GCObject *o) { + global_State *g = G(L); + lua_assert(g->allgc == o); /* object must be 1st in 'allgc' list! */ + white2gray(o); /* they will be gray forever */ + g->allgc = o->next; /* remove object from 'allgc' list */ + o->next = g->fixedgc; /* link it to 'fixedgc' list */ + g->fixedgc = o; +} + + +/* +** create a new collectable object (with given type and size) and link +** it to 'allgc' list. +*/ +GCObject *luaC_newobj (lua_State *L, int tt, size_t sz) { + global_State *g = G(L); + GCObject *o = cast(GCObject *, luaM_newobject(L, novariant(tt), sz)); + o->marked = luaC_white(g); + o->tt = tt; + o->next = g->allgc; + g->allgc = o; + return o; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Mark functions +** ======================================================= +*/ + + +/* +** mark an object. Userdata, strings, and closed upvalues are visited +** and turned black here. Other objects are marked gray and added +** to appropriate list to be visited (and turned black) later. (Open +** upvalues are already linked in 'headuv' list.) +*/ +static void reallymarkobject (global_State *g, GCObject *o) { + reentry: + white2gray(o); + switch (o->tt) { + case LUA_TSHRSTR: { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->shrlen); + break; + } + case LUA_TLNGSTR: { + gray2black(o); + g->GCmemtrav += sizelstring(gco2ts(o)->u.lnglen); + break; + } + case LUA_TUSERDATA: { + TValue uvalue; + markobjectN(g, gco2u(o)->metatable); /* mark its metatable */ + gray2black(o); + g->GCmemtrav += sizeudata(gco2u(o)); + getuservalue(g->mainthread, gco2u(o), &uvalue); + if (valiswhite(&uvalue)) { /* markvalue(g, &uvalue); */ + o = gcvalue(&uvalue); + goto reentry; + } + break; + } + case LUA_TLCL: { + linkgclist(gco2lcl(o), g->gray); + break; + } + case LUA_TCCL: { + linkgclist(gco2ccl(o), g->gray); + break; + } + case LUA_TTABLE: { + linkgclist(gco2t(o), g->gray); + break; + } + case LUA_TTHREAD: { + linkgclist(gco2th(o), g->gray); + break; + } + case LUA_TPROTO: { + linkgclist(gco2p(o), g->gray); + break; + } + default: lua_assert(0); break; + } +} + + +/* +** mark metamethods for basic types +*/ +static void markmt (global_State *g) { + int i; + for (i=0; i < LUA_NUMTAGS; i++) + markobjectN(g, g->mt[i]); +} + + +/* +** mark all objects in list of being-finalized +*/ +static void markbeingfnz (global_State *g) { + GCObject *o; + for (o = g->tobefnz; o != NULL; o = o->next) + markobject(g, o); +} + + +/* +** Mark all values stored in marked open upvalues from non-marked threads. +** (Values from marked threads were already marked when traversing the +** thread.) Remove from the list threads that no longer have upvalues and +** not-marked threads. +*/ +static void remarkupvals (global_State *g) { + lua_State *thread; + lua_State **p = &g->twups; + while ((thread = *p) != NULL) { + lua_assert(!isblack(thread)); /* threads are never black */ + if (isgray(thread) && thread->openupval != NULL) + p = &thread->twups; /* keep marked thread with upvalues in the list */ + else { /* thread is not marked or without upvalues */ + UpVal *uv; + *p = thread->twups; /* remove thread from the list */ + thread->twups = thread; /* mark that it is out of list */ + for (uv = thread->openupval; uv != NULL; uv = uv->u.open.next) { + if (uv->u.open.touched) { + markvalue(g, uv->v); /* remark upvalue's value */ + uv->u.open.touched = 0; + } + } + } + } +} + + +/* +** mark root set and reset all gray lists, to start a new collection +*/ +static void restartcollection (global_State *g) { + g->gray = g->grayagain = NULL; + g->weak = g->allweak = g->ephemeron = NULL; + markobject(g, g->mainthread); + markvalue(g, &g->l_registry); + markmt(g); + markbeingfnz(g); /* mark any finalizing object left from previous cycle */ +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Traverse functions +** ======================================================= +*/ + +/* +** Traverse a table with weak values and link it to proper list. During +** propagate phase, keep it in 'grayagain' list, to be revisited in the +** atomic phase. In the atomic phase, if table has any white value, +** put it in 'weak' list, to be cleared. +*/ +static void traverseweakvalue (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + /* if there is array part, assume it may have white values (it is not + worth traversing it now just to check) */ + int hasclears = (h->sizearray > 0); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + if (!hasclears && iscleared(g, gval(n))) /* is there a white value? */ + hasclears = 1; /* table will have to be cleared */ + } + } + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasclears) + linkgclist(h, g->weak); /* has to be cleared later */ +} + + +/* +** Traverse an ephemeron table and link it to proper list. Returns true +** iff any object was marked during this traversal (which implies that +** convergence has to continue). During propagation phase, keep table +** in 'grayagain' list, to be visited again in the atomic phase. In +** the atomic phase, if table has any white->white entry, it has to +** be revisited during ephemeron convergence (as that key may turn +** black). Otherwise, if it has any white key, table has to be cleared +** (in the atomic phase). +*/ +static int traverseephemeron (global_State *g, Table *h) { + int marked = 0; /* true if an object is marked in this traversal */ + int hasclears = 0; /* true if table has white keys */ + int hasww = 0; /* true if table has entry "white-key -> white-value" */ + Node *n, *limit = gnodelast(h); + unsigned int i; + /* traverse array part */ + for (i = 0; i < h->sizearray; i++) { + if (valiswhite(&h->array[i])) { + marked = 1; + reallymarkobject(g, gcvalue(&h->array[i])); + } + } + /* traverse hash part */ + for (n = gnode(h, 0); n < limit; n++) { + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else if (iscleared(g, gkey(n))) { /* key is not marked (yet)? */ + hasclears = 1; /* table must be cleared */ + if (valiswhite(gval(n))) /* value not marked yet? */ + hasww = 1; /* white-white entry */ + } + else if (valiswhite(gval(n))) { /* value not marked yet? */ + marked = 1; + reallymarkobject(g, gcvalue(gval(n))); /* mark it now */ + } + } + /* link table into proper list */ + if (g->gcstate == GCSpropagate) + linkgclist(h, g->grayagain); /* must retraverse it in atomic phase */ + else if (hasww) /* table has white->white entries? */ + linkgclist(h, g->ephemeron); /* have to propagate again */ + else if (hasclears) /* table has white keys? */ + linkgclist(h, g->allweak); /* may have to clean white keys */ + return marked; +} + + +static void traversestrongtable (global_State *g, Table *h) { + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) /* traverse array part */ + markvalue(g, &h->array[i]); + for (n = gnode(h, 0); n < limit; n++) { /* traverse hash part */ + checkdeadkey(n); + if (ttisnil(gval(n))) /* entry is empty? */ + removeentry(n); /* remove it */ + else { + lua_assert(!ttisnil(gkey(n))); + markvalue(g, gkey(n)); /* mark key */ + markvalue(g, gval(n)); /* mark value */ + } + } +} + + +static lu_mem traversetable (global_State *g, Table *h) { + const char *weakkey, *weakvalue; + const TValue *mode = gfasttm(g, h->metatable, TM_MODE); + markobjectN(g, h->metatable); + if (mode && ttisstring(mode) && /* is there a weak mode? */ + ((weakkey = strchr(svalue(mode), 'k')), + (weakvalue = strchr(svalue(mode), 'v')), + (weakkey || weakvalue))) { /* is really weak? */ + black2gray(h); /* keep table gray */ + if (!weakkey) /* strong keys? */ + traverseweakvalue(g, h); + else if (!weakvalue) /* strong values? */ + traverseephemeron(g, h); + else /* all weak */ + linkgclist(h, g->allweak); /* nothing to traverse now */ + } + else /* not weak */ + traversestrongtable(g, h); + return sizeof(Table) + sizeof(TValue) * h->sizearray + + sizeof(Node) * cast(size_t, allocsizenode(h)); +} + + +/* +** Traverse a prototype. (While a prototype is being build, its +** arrays can be larger than needed; the extra slots are filled with +** NULL, so the use of 'markobjectN') +*/ +static int traverseproto (global_State *g, Proto *f) { + int i; + if (f->cache && iswhite(f->cache)) + f->cache = NULL; /* allow cache to be collected */ + markobjectN(g, f->source); + for (i = 0; i < f->sizek; i++) /* mark literals */ + markvalue(g, &f->k[i]); + for (i = 0; i < f->sizeupvalues; i++) /* mark upvalue names */ + markobjectN(g, f->upvalues[i].name); + for (i = 0; i < f->sizep; i++) /* mark nested protos */ + markobjectN(g, f->p[i]); + for (i = 0; i < f->sizelocvars; i++) /* mark local-variable names */ + markobjectN(g, f->locvars[i].varname); + return sizeof(Proto) + sizeof(Instruction) * f->sizecode + + sizeof(Proto *) * f->sizep + + sizeof(TValue) * f->sizek + + sizeof(int) * f->sizelineinfo + + sizeof(LocVar) * f->sizelocvars + + sizeof(Upvaldesc) * f->sizeupvalues; +} + + +static lu_mem traverseCclosure (global_State *g, CClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) /* mark its upvalues */ + markvalue(g, &cl->upvalue[i]); + return sizeCclosure(cl->nupvalues); +} + +/* +** open upvalues point to values in a thread, so those values should +** be marked when the thread is traversed except in the atomic phase +** (because then the value cannot be changed by the thread and the +** thread may not be traversed again) +*/ +static lu_mem traverseLclosure (global_State *g, LClosure *cl) { + int i; + markobjectN(g, cl->p); /* mark its prototype */ + for (i = 0; i < cl->nupvalues; i++) { /* mark its upvalues */ + UpVal *uv = cl->upvals[i]; + if (uv != NULL) { + if (upisopen(uv) && g->gcstate != GCSinsideatomic) + uv->u.open.touched = 1; /* can be marked in 'remarkupvals' */ + else + markvalue(g, uv->v); + } + } + return sizeLclosure(cl->nupvalues); +} + + +static lu_mem traversethread (global_State *g, lua_State *th) { + StkId o = th->stack; + if (o == NULL) + return 1; /* stack not completely built yet */ + lua_assert(g->gcstate == GCSinsideatomic || + th->openupval == NULL || isintwups(th)); + for (; o < th->top; o++) /* mark live elements in the stack */ + markvalue(g, o); + if (g->gcstate == GCSinsideatomic) { /* final traversal? */ + StkId lim = th->stack + th->stacksize; /* real end of stack */ + for (; o < lim; o++) /* clear not-marked stack slice */ + setnilvalue(o); + /* 'remarkupvals' may have removed thread from 'twups' list */ + if (!isintwups(th) && th->openupval != NULL) { + th->twups = g->twups; /* link it back to the list */ + g->twups = th; + } + } + else if (g->gckind != KGC_EMERGENCY) + luaD_shrinkstack(th); /* do not change stack in emergency cycle */ + return (sizeof(lua_State) + sizeof(TValue) * th->stacksize + + sizeof(CallInfo) * th->nci); +} + + +/* +** traverse one gray object, turning it to black (except for threads, +** which are always gray). +*/ +static void propagatemark (global_State *g) { + lu_mem size; + GCObject *o = g->gray; + lua_assert(isgray(o)); + gray2black(o); + switch (o->tt) { + case LUA_TTABLE: { + Table *h = gco2t(o); + g->gray = h->gclist; /* remove from 'gray' list */ + size = traversetable(g, h); + break; + } + case LUA_TLCL: { + LClosure *cl = gco2lcl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseLclosure(g, cl); + break; + } + case LUA_TCCL: { + CClosure *cl = gco2ccl(o); + g->gray = cl->gclist; /* remove from 'gray' list */ + size = traverseCclosure(g, cl); + break; + } + case LUA_TTHREAD: { + lua_State *th = gco2th(o); + g->gray = th->gclist; /* remove from 'gray' list */ + linkgclist(th, g->grayagain); /* insert into 'grayagain' list */ + black2gray(o); + size = traversethread(g, th); + break; + } + case LUA_TPROTO: { + Proto *p = gco2p(o); + g->gray = p->gclist; /* remove from 'gray' list */ + size = traverseproto(g, p); + break; + } + default: lua_assert(0); return; + } + g->GCmemtrav += size; +} + + +static void propagateall (global_State *g) { + while (g->gray) propagatemark(g); +} + + +static void convergeephemerons (global_State *g) { + int changed; + do { + GCObject *w; + GCObject *next = g->ephemeron; /* get ephemeron list */ + g->ephemeron = NULL; /* tables may return to this list when traversed */ + changed = 0; + while ((w = next) != NULL) { + next = gco2t(w)->gclist; + if (traverseephemeron(g, gco2t(w))) { /* traverse marked some value? */ + propagateall(g); /* propagate changes */ + changed = 1; /* will have to revisit all ephemeron tables */ + } + } + } while (changed); +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Sweep Functions +** ======================================================= +*/ + + +/* +** clear entries with unmarked keys from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearkeys (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && (iscleared(g, gkey(n)))) { + setnilvalue(gval(n)); /* remove value ... */ + } + if (ttisnil(gval(n))) /* is entry empty? */ + removeentry(n); /* remove entry from table */ + } + } +} + + +/* +** clear entries with unmarked values from all weaktables in list 'l' up +** to element 'f' +*/ +static void clearvalues (global_State *g, GCObject *l, GCObject *f) { + for (; l != f; l = gco2t(l)->gclist) { + Table *h = gco2t(l); + Node *n, *limit = gnodelast(h); + unsigned int i; + for (i = 0; i < h->sizearray; i++) { + TValue *o = &h->array[i]; + if (iscleared(g, o)) /* value was collected? */ + setnilvalue(o); /* remove value */ + } + for (n = gnode(h, 0); n < limit; n++) { + if (!ttisnil(gval(n)) && iscleared(g, gval(n))) { + setnilvalue(gval(n)); /* remove value ... */ + removeentry(n); /* and remove entry from table */ + } + } + } +} + + +void luaC_upvdeccount (lua_State *L, UpVal *uv) { + lua_assert(uv->refcount > 0); + uv->refcount--; + if (uv->refcount == 0 && !upisopen(uv)) + luaM_free(L, uv); +} + + +static void freeLclosure (lua_State *L, LClosure *cl) { + int i; + for (i = 0; i < cl->nupvalues; i++) { + UpVal *uv = cl->upvals[i]; + if (uv) + luaC_upvdeccount(L, uv); + } + luaM_freemem(L, cl, sizeLclosure(cl->nupvalues)); +} + + +static void freeobj (lua_State *L, GCObject *o) { + switch (o->tt) { + case LUA_TPROTO: luaF_freeproto(L, gco2p(o)); break; + case LUA_TLCL: { + freeLclosure(L, gco2lcl(o)); + break; + } + case LUA_TCCL: { + luaM_freemem(L, o, sizeCclosure(gco2ccl(o)->nupvalues)); + break; + } + case LUA_TTABLE: luaH_free(L, gco2t(o)); break; + case LUA_TTHREAD: luaE_freethread(L, gco2th(o)); break; + case LUA_TUSERDATA: luaM_freemem(L, o, sizeudata(gco2u(o))); break; + case LUA_TSHRSTR: + luaS_remove(L, gco2ts(o)); /* remove it from hash table */ + luaM_freemem(L, o, sizelstring(gco2ts(o)->shrlen)); + break; + case LUA_TLNGSTR: { + luaM_freemem(L, o, sizelstring(gco2ts(o)->u.lnglen)); + break; + } + default: lua_assert(0); + } +} + + +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); + + +/* +** sweep at most 'count' elements from a list of GCObjects erasing dead +** objects, where a dead object is one marked with the old (non current) +** white; change all non-dead objects back to white, preparing for next +** collection cycle. Return where to continue the traversal or NULL if +** list is finished. +*/ +static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count) { + global_State *g = G(L); + int ow = otherwhite(g); + int white = luaC_white(g); /* current white */ + while (*p != NULL && count-- > 0) { + GCObject *curr = *p; + int marked = curr->marked; + if (isdeadm(ow, marked)) { /* is 'curr' dead? */ + *p = curr->next; /* remove 'curr' from list */ + freeobj(L, curr); /* erase 'curr' */ + } + else { /* change mark to 'white' */ + curr->marked = cast_byte((marked & maskcolors) | white); + p = &curr->next; /* go to next element */ + } + } + return (*p == NULL) ? NULL : p; +} + + +/* +** sweep a list until a live object (or end of list) +*/ +static GCObject **sweeptolive (lua_State *L, GCObject **p) { + GCObject **old = p; + do { + p = sweeplist(L, p, 1); + } while (p == old); + return p; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** Finalization +** ======================================================= +*/ + +/* +** If possible, shrink string table +*/ +static void checkSizes (lua_State *L, global_State *g) { + if (g->gckind != KGC_EMERGENCY) { + l_mem olddebt = g->GCdebt; + if (g->strt.nuse < g->strt.size / 4) /* string table too big? */ + luaS_resize(L, g->strt.size / 2); /* shrink it a little */ + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + } +} + + +static GCObject *udata2finalize (global_State *g) { + GCObject *o = g->tobefnz; /* get first element */ + lua_assert(tofinalize(o)); + g->tobefnz = o->next; /* remove it from 'tobefnz' list */ + o->next = g->allgc; /* return it to 'allgc' list */ + g->allgc = o; + resetbit(o->marked, FINALIZEDBIT); /* object is "normal" again */ + if (issweepphase(g)) + makewhite(g, o); /* "sweep" object */ + return o; +} + + +static void dothecall (lua_State *L, void *ud) { + UNUSED(ud); + luaD_callnoyield(L, L->top - 2, 0); +} + + +static void GCTM (lua_State *L, int propagateerrors) { + global_State *g = G(L); + const TValue *tm; + TValue v; + setgcovalue(L, &v, udata2finalize(g)); + tm = luaT_gettmbyobj(L, &v, TM_GC); + if (tm != NULL && ttisfunction(tm)) { /* is there a finalizer? */ + int status; + lu_byte oldah = L->allowhook; + int running = g->gcrunning; + L->allowhook = 0; /* stop debug hooks during GC metamethod */ + g->gcrunning = 0; /* avoid GC steps */ + setobj2s(L, L->top, tm); /* push finalizer... */ + setobj2s(L, L->top + 1, &v); /* ... and its argument */ + L->top += 2; /* and (next line) call the finalizer */ + L->ci->callstatus |= CIST_FIN; /* will run a finalizer */ + status = luaD_pcall(L, dothecall, NULL, savestack(L, L->top - 2), 0); + L->ci->callstatus &= ~CIST_FIN; /* not running a finalizer anymore */ + L->allowhook = oldah; /* restore hooks */ + g->gcrunning = running; /* restore state */ + if (status != LUA_OK && propagateerrors) { /* error while running __gc? */ + if (status == LUA_ERRRUN) { /* is there an error object? */ + const char *msg = (ttisstring(L->top - 1)) + ? svalue(L->top - 1) + : "no message"; + luaO_pushfstring(L, "error in __gc metamethod (%s)", msg); + status = LUA_ERRGCMM; /* error in __gc metamethod */ + } + luaD_throw(L, status); /* re-throw error */ + } + } +} + + +/* +** call a few (up to 'g->gcfinnum') finalizers +*/ +static int runafewfinalizers (lua_State *L) { + global_State *g = G(L); + unsigned int i; + lua_assert(!g->tobefnz || g->gcfinnum > 0); + for (i = 0; g->tobefnz && i < g->gcfinnum; i++) + GCTM(L, 1); /* call one finalizer */ + g->gcfinnum = (!g->tobefnz) ? 0 /* nothing more to finalize? */ + : g->gcfinnum * 2; /* else call a few more next time */ + return i; +} + + +/* +** call all pending finalizers +*/ +static void callallpendingfinalizers (lua_State *L) { + global_State *g = G(L); + while (g->tobefnz) + GCTM(L, 0); +} + + +/* +** find last 'next' field in list 'p' list (to add elements in its end) +*/ +static GCObject **findlast (GCObject **p) { + while (*p != NULL) + p = &(*p)->next; + return p; +} + + +/* +** move all unreachable objects (or 'all' objects) that need +** finalization from list 'finobj' to list 'tobefnz' (to be finalized) +*/ +static void separatetobefnz (global_State *g, int all) { + GCObject *curr; + GCObject **p = &g->finobj; + GCObject **lastnext = findlast(&g->tobefnz); + while ((curr = *p) != NULL) { /* traverse all finalizable objects */ + lua_assert(tofinalize(curr)); + if (!(iswhite(curr) || all)) /* not being collected? */ + p = &curr->next; /* don't bother with it */ + else { + *p = curr->next; /* remove 'curr' from 'finobj' list */ + curr->next = *lastnext; /* link at the end of 'tobefnz' list */ + *lastnext = curr; + lastnext = &curr->next; + } + } +} + + +/* +** if object 'o' has a finalizer, remove it from 'allgc' list (must +** search the list to find it) and link it in 'finobj' list. +*/ +void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt) { + global_State *g = G(L); + if (tofinalize(o) || /* obj. is already marked... */ + gfasttm(g, mt, TM_GC) == NULL) /* or has no finalizer? */ + return; /* nothing to be done */ + else { /* move 'o' to 'finobj' list */ + GCObject **p; + if (issweepphase(g)) { + makewhite(g, o); /* "sweep" object 'o' */ + if (g->sweepgc == &o->next) /* should not remove 'sweepgc' object */ + g->sweepgc = sweeptolive(L, g->sweepgc); /* change 'sweepgc' */ + } + /* search for pointer pointing to 'o' */ + for (p = &g->allgc; *p != o; p = &(*p)->next) { /* empty */ } + *p = o->next; /* remove 'o' from 'allgc' list */ + o->next = g->finobj; /* link it in 'finobj' list */ + g->finobj = o; + l_setbit(o->marked, FINALIZEDBIT); /* mark it as such */ + } +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** GC control +** ======================================================= +*/ + + +/* +** Set a reasonable "time" to wait before starting a new GC cycle; cycle +** will start when memory use hits threshold. (Division by 'estimate' +** should be OK: it cannot be zero (because Lua cannot even start with +** less than PAUSEADJ bytes). +*/ +static void setpause (global_State *g) { + l_mem threshold, debt; + l_mem estimate = g->GCestimate / PAUSEADJ; /* adjust 'estimate' */ + lua_assert(estimate > 0); + threshold = (g->gcpause < MAX_LMEM / estimate) /* overflow? */ + ? estimate * g->gcpause /* no overflow */ + : MAX_LMEM; /* overflow; truncate to maximum */ + debt = gettotalbytes(g) - threshold; + luaE_setdebt(g, debt); +} + + +/* +** Enter first sweep phase. +** The call to 'sweeplist' tries to make pointer point to an object +** inside the list (instead of to the header), so that the real sweep do +** not need to skip objects created between "now" and the start of the +** real sweep. +*/ +static void entersweep (lua_State *L) { + global_State *g = G(L); + g->gcstate = GCSswpallgc; + lua_assert(g->sweepgc == NULL); + g->sweepgc = sweeplist(L, &g->allgc, 1); +} + + +void luaC_freeallobjects (lua_State *L) { + global_State *g = G(L); + separatetobefnz(g, 1); /* separate all objects with finalizers */ + lua_assert(g->finobj == NULL); + callallpendingfinalizers(L); + lua_assert(g->tobefnz == NULL); + g->currentwhite = WHITEBITS; /* this "white" makes all objects look dead */ + g->gckind = KGC_NORMAL; + sweepwholelist(L, &g->finobj); + sweepwholelist(L, &g->allgc); + sweepwholelist(L, &g->fixedgc); /* collect fixed objects */ + lua_assert(g->strt.nuse == 0); +} + + +static l_mem atomic (lua_State *L) { + global_State *g = G(L); + l_mem work; + GCObject *origweak, *origall; + GCObject *grayagain = g->grayagain; /* save original list */ + lua_assert(g->ephemeron == NULL && g->weak == NULL); + lua_assert(!iswhite(g->mainthread)); + g->gcstate = GCSinsideatomic; + g->GCmemtrav = 0; /* start counting work */ + markobject(g, L); /* mark running thread */ + /* registry and global metatables may be changed by API */ + markvalue(g, &g->l_registry); + markmt(g); /* mark global metatables */ + /* remark occasional upvalues of (maybe) dead threads */ + remarkupvals(g); + propagateall(g); /* propagate changes */ + work = g->GCmemtrav; /* stop counting (do not recount 'grayagain') */ + g->gray = grayagain; + propagateall(g); /* traverse 'grayagain' list */ + g->GCmemtrav = 0; /* restart counting */ + convergeephemerons(g); + /* at this point, all strongly accessible objects are marked. */ + /* Clear values from weak tables, before checking finalizers */ + clearvalues(g, g->weak, NULL); + clearvalues(g, g->allweak, NULL); + origweak = g->weak; origall = g->allweak; + work += g->GCmemtrav; /* stop counting (objects being finalized) */ + separatetobefnz(g, 0); /* separate objects to be finalized */ + g->gcfinnum = 1; /* there may be objects to be finalized */ + markbeingfnz(g); /* mark objects that will be finalized */ + propagateall(g); /* remark, to propagate 'resurrection' */ + g->GCmemtrav = 0; /* restart counting */ + convergeephemerons(g); + /* at this point, all resurrected objects are marked. */ + /* remove dead objects from weak tables */ + clearkeys(g, g->ephemeron, NULL); /* clear keys from all ephemeron tables */ + clearkeys(g, g->allweak, NULL); /* clear keys from all 'allweak' tables */ + /* clear values from resurrected weak tables */ + clearvalues(g, g->weak, origweak); + clearvalues(g, g->allweak, origall); + luaS_clearcache(g); + g->currentwhite = cast_byte(otherwhite(g)); /* flip current white */ + work += g->GCmemtrav; /* complete counting */ + return work; /* estimate of memory marked by 'atomic' */ +} + + +static lu_mem sweepstep (lua_State *L, global_State *g, + int nextstate, GCObject **nextlist) { + if (g->sweepgc) { + l_mem olddebt = g->GCdebt; + g->sweepgc = sweeplist(L, g->sweepgc, GCSWEEPMAX); + g->GCestimate += g->GCdebt - olddebt; /* update estimate */ + if (g->sweepgc) /* is there still something to sweep? */ + return (GCSWEEPMAX * GCSWEEPCOST); + } + /* else enter next state */ + g->gcstate = nextstate; + g->sweepgc = nextlist; + return 0; +} + + +static lu_mem singlestep (lua_State *L) { + global_State *g = G(L); + switch (g->gcstate) { + case GCSpause: { + g->GCmemtrav = g->strt.size * sizeof(GCObject*); + restartcollection(g); + g->gcstate = GCSpropagate; + return g->GCmemtrav; + } + case GCSpropagate: { + g->GCmemtrav = 0; + lua_assert(g->gray); + propagatemark(g); + if (g->gray == NULL) /* no more gray objects? */ + g->gcstate = GCSatomic; /* finish propagate phase */ + return g->GCmemtrav; /* memory traversed in this step */ + } + case GCSatomic: { + lu_mem work; + propagateall(g); /* make sure gray list is empty */ + work = atomic(L); /* work is what was traversed by 'atomic' */ + entersweep(L); + g->GCestimate = gettotalbytes(g); /* first estimate */; + return work; + } + case GCSswpallgc: { /* sweep "regular" objects */ + return sweepstep(L, g, GCSswpfinobj, &g->finobj); + } + case GCSswpfinobj: { /* sweep objects with finalizers */ + return sweepstep(L, g, GCSswptobefnz, &g->tobefnz); + } + case GCSswptobefnz: { /* sweep objects to be finalized */ + return sweepstep(L, g, GCSswpend, NULL); + } + case GCSswpend: { /* finish sweeps */ + makewhite(g, g->mainthread); /* sweep main thread */ + checkSizes(L, g); + g->gcstate = GCScallfin; + return 0; + } + case GCScallfin: { /* call remaining finalizers */ + if (g->tobefnz && g->gckind != KGC_EMERGENCY) { + int n = runafewfinalizers(L); + return (n * GCFINALIZECOST); + } + else { /* emergency mode or no more finalizers */ + g->gcstate = GCSpause; /* finish collection */ + return 0; + } + } + default: lua_assert(0); return 0; + } +} + + +/* +** advances the garbage collector until it reaches a state allowed +** by 'statemask' +*/ +void luaC_runtilstate (lua_State *L, int statesmask) { + global_State *g = G(L); + while (!testbit(statesmask, g->gcstate)) + singlestep(L); +} + + +/* +** get GC debt and convert it from Kb to 'work units' (avoid zero debt +** and overflows) +*/ +static l_mem getdebt (global_State *g) { + l_mem debt = g->GCdebt; + int stepmul = g->gcstepmul; + if (debt <= 0) return 0; /* minimal debt */ + else { + debt = (debt / STEPMULADJ) + 1; + debt = (debt < MAX_LMEM / stepmul) ? debt * stepmul : MAX_LMEM; + return debt; + } +} + +/* +** performs a basic GC step when collector is running +*/ +void luaC_step (lua_State *L) { + global_State *g = G(L); + l_mem debt = getdebt(g); /* GC deficit (be paid now) */ + if (!g->gcrunning) { /* not running? */ + luaE_setdebt(g, -GCSTEPSIZE * 10); /* avoid being called too often */ + return; + } + do { /* repeat until pause or enough "credit" (negative debt) */ + lu_mem work = singlestep(L); /* perform one single step */ + debt -= work; + } while (debt > -GCSTEPSIZE && g->gcstate != GCSpause); + if (g->gcstate == GCSpause) + setpause(g); /* pause until next cycle */ + else { + debt = (debt / g->gcstepmul) * STEPMULADJ; /* convert 'work units' to Kb */ + luaE_setdebt(g, debt); + runafewfinalizers(L); + } +} + + +/* +** Performs a full GC cycle; if 'isemergency', set a flag to avoid +** some operations which could change the interpreter state in some +** unexpected ways (running finalizers and shrinking some structures). +** Before running the collection, check 'keepinvariant'; if it is true, +** there may be some objects marked as black, so the collector has +** to sweep all objects to turn them back to white (as white has not +** changed, nothing will be collected). +*/ +void luaC_fullgc (lua_State *L, int isemergency) { + global_State *g = G(L); + lua_assert(g->gckind == KGC_NORMAL); + if (isemergency) g->gckind = KGC_EMERGENCY; /* set flag */ + if (keepinvariant(g)) { /* black objects? */ + entersweep(L); /* sweep everything to turn them back to white */ + } + /* finish any pending sweep phase to start a new cycle */ + luaC_runtilstate(L, bitmask(GCSpause)); + luaC_runtilstate(L, ~bitmask(GCSpause)); /* start new collection */ + luaC_runtilstate(L, bitmask(GCScallfin)); /* run up to finalizers */ + /* estimate must be correct after a full GC cycle */ + lua_assert(g->GCestimate == gettotalbytes(g)); + luaC_runtilstate(L, bitmask(GCSpause)); /* finish collection */ + g->gckind = KGC_NORMAL; + setpause(g); +} + +/* }====================================================== */ + + diff --git a/src/lua/lgc.h b/src/lua/lgc.h new file mode 100644 index 000000000000..425cd7cef34c --- /dev/null +++ b/src/lua/lgc.h @@ -0,0 +1,147 @@ +/* +** $Id: lgc.h,v 2.91.1.1 2017/04/19 17:39:34 roberto Exp $ +** Garbage Collector +** See Copyright Notice in lua.h +*/ + +#ifndef lgc_h +#define lgc_h + + +#include "lobject.h" +#include "lstate.h" + +/* +** Collectable objects may have one of three colors: white, which +** means the object is not marked; gray, which means the +** object is marked, but its references may be not marked; and +** black, which means that the object and all its references are marked. +** The main invariant of the garbage collector, while marking objects, +** is that a black object can never point to a white one. Moreover, +** any gray object must be in a "gray list" (gray, grayagain, weak, +** allweak, ephemeron) so that it can be visited again before finishing +** the collection cycle. These lists have no meaning when the invariant +** is not being enforced (e.g., sweep phase). +*/ + + + +/* how much to allocate before next GC step */ +#if !defined(GCSTEPSIZE) +/* ~100 small strings */ +#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) +#endif + + +/* +** Possible states of the Garbage Collector +*/ +#define GCSpropagate 0 +#define GCSatomic 1 +#define GCSswpallgc 2 +#define GCSswpfinobj 3 +#define GCSswptobefnz 4 +#define GCSswpend 5 +#define GCScallfin 6 +#define GCSpause 7 + + +#define issweepphase(g) \ + (GCSswpallgc <= (g)->gcstate && (g)->gcstate <= GCSswpend) + + +/* +** macro to tell when main invariant (white objects cannot point to black +** ones) must be kept. During a collection, the sweep +** phase may break the invariant, as objects turned white may point to +** still-black objects. The invariant is restored when sweep ends and +** all objects are white again. +*/ + +#define keepinvariant(g) ((g)->gcstate <= GCSatomic) + + +/* +** some useful bit tricks +*/ +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) + + +/* Layout for bit use in 'marked' field: */ +#define WHITE0BIT 0 /* object is white (type 0) */ +#define WHITE1BIT 1 /* object is white (type 1) */ +#define BLACKBIT 2 /* object is black */ +#define FINALIZEDBIT 3 /* object has been marked for finalization */ +/* bit 7 is currently used by tests (luaL_checkmemory) */ + +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) + + +#define iswhite(x) testbits((x)->marked, WHITEBITS) +#define isblack(x) testbit((x)->marked, BLACKBIT) +#define isgray(x) /* neither white nor black */ \ + (!testbits((x)->marked, WHITEBITS | bitmask(BLACKBIT))) + +#define tofinalize(x) testbit((x)->marked, FINALIZEDBIT) + +#define otherwhite(g) ((g)->currentwhite ^ WHITEBITS) +#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->marked) + +#define changewhite(x) ((x)->marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->marked, BLACKBIT) + +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) + + +/* +** Does one step of collection when debt becomes positive. 'pre'/'pos' +** allows some adjustments to be done only when needed. macro +** 'condchangemem' is used only for heavy tests (forcing a full +** GC cycle on every opportunity) +*/ +#define luaC_condGC(L,pre,pos) \ + { if (G(L)->GCdebt > 0) { pre; luaC_step(L); pos;}; \ + condchangemem(L,pre,pos); } + +/* more often than not, 'pre'/'pos' are empty */ +#define luaC_checkGC(L) luaC_condGC(L,(void)0,(void)0) + + +#define luaC_barrier(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrier_(L,obj2gco(p),gcvalue(v)) : cast_void(0)) + +#define luaC_barrierback(L,p,v) ( \ + (iscollectable(v) && isblack(p) && iswhite(gcvalue(v))) ? \ + luaC_barrierback_(L,p) : cast_void(0)) + +#define luaC_objbarrier(L,p,o) ( \ + (isblack(p) && iswhite(o)) ? \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)) : cast_void(0)) + +#define luaC_upvalbarrier(L,uv) ( \ + (iscollectable((uv)->v) && !upisopen(uv)) ? \ + luaC_upvalbarrier_(L,uv) : cast_void(0)) + +LUAI_FUNC void luaC_fix (lua_State *L, GCObject *o); +LUAI_FUNC void luaC_freeallobjects (lua_State *L); +LUAI_FUNC void luaC_step (lua_State *L); +LUAI_FUNC void luaC_runtilstate (lua_State *L, int statesmask); +LUAI_FUNC void luaC_fullgc (lua_State *L, int isemergency); +LUAI_FUNC GCObject *luaC_newobj (lua_State *L, int tt, size_t sz); +LUAI_FUNC void luaC_barrier_ (lua_State *L, GCObject *o, GCObject *v); +LUAI_FUNC void luaC_barrierback_ (lua_State *L, Table *o); +LUAI_FUNC void luaC_upvalbarrier_ (lua_State *L, UpVal *uv); +LUAI_FUNC void luaC_checkfinalizer (lua_State *L, GCObject *o, Table *mt); +LUAI_FUNC void luaC_upvdeccount (lua_State *L, UpVal *uv); + + +#endif diff --git a/src/lua/linit.c b/src/lua/linit.c new file mode 100644 index 000000000000..480da52c7e54 --- /dev/null +++ b/src/lua/linit.c @@ -0,0 +1,68 @@ +/* +** $Id: linit.c,v 1.39.1.1 2017/04/19 17:20:42 roberto Exp $ +** Initialization of libraries for lua.c and other clients +** See Copyright Notice in lua.h +*/ + + +#define linit_c +#define LUA_LIB + +/* +** If you embed Lua in your program and need to open the standard +** libraries, call luaL_openlibs in your program. If you need a +** different set of libraries, copy this file to your project and edit +** it to suit your needs. +** +** You can also *preload* libraries, so that a later 'require' can +** open the library, which is already linked to the application. +** For that, do the following code: +** +** luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); +** lua_pushcfunction(L, luaopen_modname); +** lua_setfield(L, -2, modname); +** lua_pop(L, 1); // remove PRELOAD table +*/ + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lualib.h" +#include "lauxlib.h" + + +/* +** these libs are loaded by lua.c and are readily available to any Lua +** program +*/ +static const luaL_Reg loadedlibs[] = { + {"_G", luaopen_base}, + {LUA_LOADLIBNAME, luaopen_package}, + {LUA_COLIBNAME, luaopen_coroutine}, + {LUA_TABLIBNAME, luaopen_table}, + {LUA_IOLIBNAME, luaopen_io}, + {LUA_OSLIBNAME, luaopen_os}, + {LUA_STRLIBNAME, luaopen_string}, + {LUA_MATHLIBNAME, luaopen_math}, + {LUA_UTF8LIBNAME, luaopen_utf8}, + {LUA_DBLIBNAME, luaopen_debug}, +#if defined(LUA_COMPAT_BITLIB) + {LUA_BITLIBNAME, luaopen_bit32}, +#endif + {NULL, NULL} +}; + + +LUALIB_API void luaL_openlibs (lua_State *L) { + const luaL_Reg *lib; + /* "require" functions from 'loadedlibs' and set results to global table */ + for (lib = loadedlibs; lib->func; lib++) { + luaL_requiref(L, lib->name, lib->func, 1); + lua_pop(L, 1); /* remove lib */ + } +} + diff --git a/src/lua/liolib.c b/src/lua/liolib.c new file mode 100644 index 000000000000..027d4bd0db45 --- /dev/null +++ b/src/lua/liolib.c @@ -0,0 +1,778 @@ +/* +** $Id: liolib.c,v 2.151.1.1 2017/04/19 17:29:57 roberto Exp $ +** Standard I/O (and system) library +** See Copyright Notice in lua.h +*/ + +#define liolib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + + + +/* +** Change this macro to accept other modes for 'fopen' besides +** the standard ones. +*/ +#if !defined(l_checkmode) + +/* accepted extensions to 'mode' in 'fopen' */ +#if !defined(L_MODEEXT) +#define L_MODEEXT "b" +#endif + +/* Check whether 'mode' matches '[rwa]%+?[L_MODEEXT]*' */ +static int l_checkmode (const char *mode) { + return (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && + (*mode != '+' || (++mode, 1)) && /* skip if char is '+' */ + (strspn(mode, L_MODEEXT) == strlen(mode))); /* check extensions */ +} + +#endif + +/* +** {====================================================== +** l_popen spawns a new process connected to the current +** one through the file streams. +** ======================================================= +*/ + +#if !defined(l_popen) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_popen(L,c,m) (fflush(NULL), popen(c,m)) +#define l_pclose(L,file) (pclose(file)) + +#elif defined(LUA_USE_WINDOWS) /* }{ */ + +#define l_popen(L,c,m) (_popen(c,m)) +#define l_pclose(L,file) (_pclose(file)) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_popen(L,c,m) \ + ((void)((void)c, m), \ + luaL_error(L, "'popen' not supported"), \ + (FILE*)0) +#define l_pclose(L,file) ((void)L, (void)file, -1) + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +#if !defined(l_getc) /* { */ + +#if defined(LUA_USE_POSIX) +#define l_getc(f) getc_unlocked(f) +#define l_lockfile(f) flockfile(f) +#define l_unlockfile(f) funlockfile(f) +#else +#define l_getc(f) getc(f) +#define l_lockfile(f) ((void)0) +#define l_unlockfile(f) ((void)0) +#endif + +#endif /* } */ + + +/* +** {====================================================== +** l_fseek: configuration for longer offsets +** ======================================================= +*/ + +#if !defined(l_fseek) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include + +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t + +#elif defined(LUA_USE_WINDOWS) && !defined(_CRTIMP_TYPEINFO) \ + && defined(_MSC_VER) && (_MSC_VER >= 1400) /* }{ */ + +/* Windows (but not DDK) and Visual C++ 2005 or higher */ +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 + +#else /* }{ */ + +/* ISO C definitions */ +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long + +#endif /* } */ + +#endif /* } */ + +/* }====================================================== */ + + +#define IO_PREFIX "_IO_" +#define IOPREF_LEN (sizeof(IO_PREFIX)/sizeof(char) - 1) +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") + + +typedef luaL_Stream LStream; + + +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) + +#define isclosed(p) ((p)->closef == NULL) + + +static int io_type (lua_State *L) { + LStream *p; + luaL_checkany(L, 1); + p = (LStream *)luaL_testudata(L, 1, LUA_FILEHANDLE); + if (p == NULL) + lua_pushnil(L); /* not a file */ + else if (isclosed(p)) + lua_pushliteral(L, "closed file"); + else + lua_pushliteral(L, "file"); + return 1; +} + + +static int f_tostring (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + lua_pushliteral(L, "file (closed)"); + else + lua_pushfstring(L, "file (%p)", p->f); + return 1; +} + + +static FILE *tofile (lua_State *L) { + LStream *p = tolstream(L); + if (isclosed(p)) + luaL_error(L, "attempt to use a closed file"); + lua_assert(p->f); + return p->f; +} + + +/* +** When creating file handles, always creates a 'closed' file handle +** before opening the actual file; so, if there is a memory error, the +** handle is in a consistent state. +*/ +static LStream *newprefile (lua_State *L) { + LStream *p = (LStream *)lua_newuserdata(L, sizeof(LStream)); + p->closef = NULL; /* mark file handle as 'closed' */ + luaL_setmetatable(L, LUA_FILEHANDLE); + return p; +} + + +/* +** Calls the 'close' function from a file handle. The 'volatile' avoids +** a bug in some versions of the Clang compiler (e.g., clang 3.0 for +** 32 bits). +*/ +static int aux_close (lua_State *L) { + LStream *p = tolstream(L); + volatile lua_CFunction cf = p->closef; + p->closef = NULL; /* mark stream as closed */ + return (*cf)(L); /* close it */ +} + + +static int f_close (lua_State *L) { + tofile(L); /* make sure argument is an open stream */ + return aux_close(L); +} + + +static int io_close (lua_State *L) { + if (lua_isnone(L, 1)) /* no argument? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_OUTPUT); /* use standard output */ + return f_close(L); +} + + +static int f_gc (lua_State *L) { + LStream *p = tolstream(L); + if (!isclosed(p) && p->f != NULL) + aux_close(L); /* ignore closed and incompletely open files */ + return 0; +} + + +/* +** function to close regular files +*/ +static int io_fclose (lua_State *L) { + LStream *p = tolstream(L); + int res = fclose(p->f); + return luaL_fileresult(L, (res == 0), NULL); +} + + +static LStream *newfile (lua_State *L) { + LStream *p = newprefile(L); + p->f = NULL; + p->closef = &io_fclose; + return p; +} + + +static void opencheck (lua_State *L, const char *fname, const char *mode) { + LStream *p = newfile(L); + p->f = fopen(fname, mode); + if (p->f == NULL) + luaL_error(L, "cannot open file '%s' (%s)", fname, strerror(errno)); +} + + +static int io_open (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newfile(L); + const char *md = mode; /* to traverse/check mode */ + luaL_argcheck(L, l_checkmode(md), 2, "invalid mode"); + p->f = fopen(filename, mode); + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +/* +** function to close 'popen' files +*/ +static int io_pclose (lua_State *L) { + LStream *p = tolstream(L); + return luaL_execresult(L, l_pclose(L, p->f)); +} + + +static int io_popen (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + const char *mode = luaL_optstring(L, 2, "r"); + LStream *p = newprefile(L); + luaL_argcheck(L, ((mode[0] == 'r' || mode[0] == 'w') && mode[1] == '\0'), + 2, "invalid mode"); + p->f = l_popen(L, filename, mode); + p->closef = &io_pclose; + return (p->f == NULL) ? luaL_fileresult(L, 0, filename) : 1; +} + + +static int io_tmpfile (lua_State *L) { + LStream *p = newfile(L); + p->f = tmpfile(); + return (p->f == NULL) ? luaL_fileresult(L, 0, NULL) : 1; +} + + +static FILE *getiofile (lua_State *L, const char *findex) { + LStream *p; + lua_getfield(L, LUA_REGISTRYINDEX, findex); + p = (LStream *)lua_touserdata(L, -1); + if (isclosed(p)) + luaL_error(L, "standard %s file is closed", findex + IOPREF_LEN); + return p->f; +} + + +static int g_iofile (lua_State *L, const char *f, const char *mode) { + if (!lua_isnoneornil(L, 1)) { + const char *filename = lua_tostring(L, 1); + if (filename) + opencheck(L, filename, mode); + else { + tofile(L); /* check that it's a valid file handle */ + lua_pushvalue(L, 1); + } + lua_setfield(L, LUA_REGISTRYINDEX, f); + } + /* return current value */ + lua_getfield(L, LUA_REGISTRYINDEX, f); + return 1; +} + + +static int io_input (lua_State *L) { + return g_iofile(L, IO_INPUT, "r"); +} + + +static int io_output (lua_State *L) { + return g_iofile(L, IO_OUTPUT, "w"); +} + + +static int io_readline (lua_State *L); + + +/* +** maximum number of arguments to 'f:lines'/'io.lines' (it + 3 must fit +** in the limit for upvalues of a closure) +*/ +#define MAXARGLINE 250 + +static void aux_lines (lua_State *L, int toclose) { + int n = lua_gettop(L) - 1; /* number of arguments to read */ + luaL_argcheck(L, n <= MAXARGLINE, MAXARGLINE + 2, "too many arguments"); + lua_pushinteger(L, n); /* number of arguments to read */ + lua_pushboolean(L, toclose); /* close/not close file when finished */ + lua_rotate(L, 2, 2); /* move 'n' and 'toclose' to their positions */ + lua_pushcclosure(L, io_readline, 3 + n); +} + + +static int f_lines (lua_State *L) { + tofile(L); /* check that it's a valid file handle */ + aux_lines(L, 0); + return 1; +} + + +static int io_lines (lua_State *L) { + int toclose; + if (lua_isnone(L, 1)) lua_pushnil(L); /* at least one argument */ + if (lua_isnil(L, 1)) { /* no file name? */ + lua_getfield(L, LUA_REGISTRYINDEX, IO_INPUT); /* get default input */ + lua_replace(L, 1); /* put it at index 1 */ + tofile(L); /* check that it's a valid file handle */ + toclose = 0; /* do not close it after iteration */ + } + else { /* open a new file */ + const char *filename = luaL_checkstring(L, 1); + opencheck(L, filename, "r"); + lua_replace(L, 1); /* put file at index 1 */ + toclose = 1; /* close it after iteration */ + } + aux_lines(L, toclose); + return 1; +} + + +/* +** {====================================================== +** READ +** ======================================================= +*/ + + +/* maximum length of a numeral */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + + +/* auxiliary structure used by 'read_number' */ +typedef struct { + FILE *f; /* file being read */ + int c; /* current character (look ahead) */ + int n; /* number of elements in buffer 'buff' */ + char buff[L_MAXLENNUM + 1]; /* +1 for ending '\0' */ +} RN; + + +/* +** Add current char to buffer (if not out of space) and read next one +*/ +static int nextc (RN *rn) { + if (rn->n >= L_MAXLENNUM) { /* buffer overflow? */ + rn->buff[0] = '\0'; /* invalidate result */ + return 0; /* fail */ + } + else { + rn->buff[rn->n++] = rn->c; /* save current char */ + rn->c = l_getc(rn->f); /* read next one */ + return 1; + } +} + + +/* +** Accept current char if it is in 'set' (of size 2) +*/ +static int test2 (RN *rn, const char *set) { + if (rn->c == set[0] || rn->c == set[1]) + return nextc(rn); + else return 0; +} + + +/* +** Read a sequence of (hex)digits +*/ +static int readdigits (RN *rn, int hex) { + int count = 0; + while ((hex ? isxdigit(rn->c) : isdigit(rn->c)) && nextc(rn)) + count++; + return count; +} + + +/* +** Read a number: first reads a valid prefix of a numeral into a buffer. +** Then it calls 'lua_stringtonumber' to check whether the format is +** correct and to convert it to a Lua number +*/ +static int read_number (lua_State *L, FILE *f) { + RN rn; + int count = 0; + int hex = 0; + char decp[2]; + rn.f = f; rn.n = 0; + decp[0] = lua_getlocaledecpoint(); /* get decimal point from locale */ + decp[1] = '.'; /* always accept a dot */ + l_lockfile(rn.f); + do { rn.c = l_getc(rn.f); } while (isspace(rn.c)); /* skip spaces */ + test2(&rn, "-+"); /* optional signal */ + if (test2(&rn, "00")) { + if (test2(&rn, "xX")) hex = 1; /* numeral is hexadecimal */ + else count = 1; /* count initial '0' as a valid digit */ + } + count += readdigits(&rn, hex); /* integral part */ + if (test2(&rn, decp)) /* decimal point? */ + count += readdigits(&rn, hex); /* fractional part */ + if (count > 0 && test2(&rn, (hex ? "pP" : "eE"))) { /* exponent mark? */ + test2(&rn, "-+"); /* exponent signal */ + readdigits(&rn, 0); /* exponent digits */ + } + ungetc(rn.c, rn.f); /* unread look-ahead char */ + l_unlockfile(rn.f); + rn.buff[rn.n] = '\0'; /* finish string */ + if (lua_stringtonumber(L, rn.buff)) /* is this a valid number? */ + return 1; /* ok */ + else { /* invalid format */ + lua_pushnil(L); /* "result" to be removed */ + return 0; /* read fails */ + } +} + + +static int test_eof (lua_State *L, FILE *f) { + int c = getc(f); + ungetc(c, f); /* no-op when c == EOF */ + lua_pushliteral(L, ""); + return (c != EOF); +} + + +static int read_line (lua_State *L, FILE *f, int chop) { + luaL_Buffer b; + int c = '\0'; + luaL_buffinit(L, &b); + while (c != EOF && c != '\n') { /* repeat until end of line */ + char *buff = luaL_prepbuffer(&b); /* preallocate buffer */ + int i = 0; + l_lockfile(f); /* no memory errors can happen inside the lock */ + while (i < LUAL_BUFFERSIZE && (c = l_getc(f)) != EOF && c != '\n') + buff[i++] = c; + l_unlockfile(f); + luaL_addsize(&b, i); + } + if (!chop && c == '\n') /* want a newline and have one? */ + luaL_addchar(&b, c); /* add ending newline to result */ + luaL_pushresult(&b); /* close buffer */ + /* return ok if read something (either a newline or something else) */ + return (c == '\n' || lua_rawlen(L, -1) > 0); +} + + +static void read_all (lua_State *L, FILE *f) { + size_t nr; + luaL_Buffer b; + luaL_buffinit(L, &b); + do { /* read file in chunks of LUAL_BUFFERSIZE bytes */ + char *p = luaL_prepbuffer(&b); + nr = fread(p, sizeof(char), LUAL_BUFFERSIZE, f); + luaL_addsize(&b, nr); + } while (nr == LUAL_BUFFERSIZE); + luaL_pushresult(&b); /* close buffer */ +} + + +static int read_chars (lua_State *L, FILE *f, size_t n) { + size_t nr; /* number of chars actually read */ + char *p; + luaL_Buffer b; + luaL_buffinit(L, &b); + p = luaL_prepbuffsize(&b, n); /* prepare buffer to read whole block */ + nr = fread(p, sizeof(char), n, f); /* try to read 'n' chars */ + luaL_addsize(&b, nr); + luaL_pushresult(&b); /* close buffer */ + return (nr > 0); /* true iff read something */ +} + + +static int g_read (lua_State *L, FILE *f, int first) { + int nargs = lua_gettop(L) - 1; + int success; + int n; + clearerr(f); + if (nargs == 0) { /* no arguments? */ + success = read_line(L, f, 1); + n = first+1; /* to return 1 result */ + } + else { /* ensure stack space for all results and for auxlib's buffer */ + luaL_checkstack(L, nargs+LUA_MINSTACK, "too many arguments"); + success = 1; + for (n = first; nargs-- && success; n++) { + if (lua_type(L, n) == LUA_TNUMBER) { + size_t l = (size_t)luaL_checkinteger(L, n); + success = (l == 0) ? test_eof(L, f) : read_chars(L, f, l); + } + else { + const char *p = luaL_checkstring(L, n); + if (*p == '*') p++; /* skip optional '*' (for compatibility) */ + switch (*p) { + case 'n': /* number */ + success = read_number(L, f); + break; + case 'l': /* line */ + success = read_line(L, f, 1); + break; + case 'L': /* line with end-of-line */ + success = read_line(L, f, 0); + break; + case 'a': /* file */ + read_all(L, f); /* read entire file */ + success = 1; /* always success */ + break; + default: + return luaL_argerror(L, n, "invalid format"); + } + } + } + } + if (ferror(f)) + return luaL_fileresult(L, 0, NULL); + if (!success) { + lua_pop(L, 1); /* remove last result */ + lua_pushnil(L); /* push nil instead */ + } + return n - first; +} + + +static int io_read (lua_State *L) { + return g_read(L, getiofile(L, IO_INPUT), 1); +} + + +static int f_read (lua_State *L) { + return g_read(L, tofile(L), 2); +} + + +static int io_readline (lua_State *L) { + LStream *p = (LStream *)lua_touserdata(L, lua_upvalueindex(1)); + int i; + int n = (int)lua_tointeger(L, lua_upvalueindex(2)); + if (isclosed(p)) /* file is already closed? */ + return luaL_error(L, "file is already closed"); + lua_settop(L , 1); + luaL_checkstack(L, n, "too many arguments"); + for (i = 1; i <= n; i++) /* push arguments to 'g_read' */ + lua_pushvalue(L, lua_upvalueindex(3 + i)); + n = g_read(L, p->f, 2); /* 'n' is number of results */ + lua_assert(n > 0); /* should return at least a nil */ + if (lua_toboolean(L, -n)) /* read at least one value? */ + return n; /* return them */ + else { /* first result is nil: EOF or error */ + if (n > 1) { /* is there error information? */ + /* 2nd result is error message */ + return luaL_error(L, "%s", lua_tostring(L, -n + 1)); + } + if (lua_toboolean(L, lua_upvalueindex(3))) { /* generator created file? */ + lua_settop(L, 0); + lua_pushvalue(L, lua_upvalueindex(1)); + aux_close(L); /* close it */ + } + return 0; + } +} + +/* }====================================================== */ + + +static int g_write (lua_State *L, FILE *f, int arg) { + int nargs = lua_gettop(L) - arg; + int status = 1; + for (; nargs--; arg++) { + if (lua_type(L, arg) == LUA_TNUMBER) { + /* optimization: could be done exactly as for strings */ + int len = lua_isinteger(L, arg) + ? fprintf(f, LUA_INTEGER_FMT, + (LUAI_UACINT)lua_tointeger(L, arg)) + : fprintf(f, LUA_NUMBER_FMT, + (LUAI_UACNUMBER)lua_tonumber(L, arg)); + status = status && (len > 0); + } + else { + size_t l; + const char *s = luaL_checklstring(L, arg, &l); + status = status && (fwrite(s, sizeof(char), l, f) == l); + } + } + if (status) return 1; /* file handle already on stack top */ + else return luaL_fileresult(L, status, NULL); +} + + +static int io_write (lua_State *L) { + return g_write(L, getiofile(L, IO_OUTPUT), 1); +} + + +static int f_write (lua_State *L) { + FILE *f = tofile(L); + lua_pushvalue(L, 1); /* push file at the stack top (to be returned) */ + return g_write(L, f, 2); +} + + +static int f_seek (lua_State *L) { + static const int mode[] = {SEEK_SET, SEEK_CUR, SEEK_END}; + static const char *const modenames[] = {"set", "cur", "end", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, "cur", modenames); + lua_Integer p3 = luaL_optinteger(L, 3, 0); + l_seeknum offset = (l_seeknum)p3; + luaL_argcheck(L, (lua_Integer)offset == p3, 3, + "not an integer in proper range"); + op = l_fseek(f, offset, mode[op]); + if (op) + return luaL_fileresult(L, 0, NULL); /* error */ + else { + lua_pushinteger(L, (lua_Integer)l_ftell(f)); + return 1; + } +} + + +static int f_setvbuf (lua_State *L) { + static const int mode[] = {_IONBF, _IOFBF, _IOLBF}; + static const char *const modenames[] = {"no", "full", "line", NULL}; + FILE *f = tofile(L); + int op = luaL_checkoption(L, 2, NULL, modenames); + lua_Integer sz = luaL_optinteger(L, 3, LUAL_BUFFERSIZE); + int res = setvbuf(f, NULL, mode[op], (size_t)sz); + return luaL_fileresult(L, res == 0, NULL); +} + + + +static int io_flush (lua_State *L) { + return luaL_fileresult(L, fflush(getiofile(L, IO_OUTPUT)) == 0, NULL); +} + + +static int f_flush (lua_State *L) { + return luaL_fileresult(L, fflush(tofile(L)) == 0, NULL); +} + + +/* +** functions for 'io' library +*/ +static const luaL_Reg iolib[] = { + {"close", io_close}, + {"flush", io_flush}, + {"input", io_input}, + {"lines", io_lines}, + {"open", io_open}, + {"output", io_output}, + {"popen", io_popen}, + {"read", io_read}, + {"tmpfile", io_tmpfile}, + {"type", io_type}, + {"write", io_write}, + {NULL, NULL} +}; + + +/* +** methods for file handles +*/ +static const luaL_Reg flib[] = { + {"close", f_close}, + {"flush", f_flush}, + {"lines", f_lines}, + {"read", f_read}, + {"seek", f_seek}, + {"setvbuf", f_setvbuf}, + {"write", f_write}, + {"__gc", f_gc}, + {"__tostring", f_tostring}, + {NULL, NULL} +}; + + +static void createmeta (lua_State *L) { + luaL_newmetatable(L, LUA_FILEHANDLE); /* create metatable for file handles */ + lua_pushvalue(L, -1); /* push metatable */ + lua_setfield(L, -2, "__index"); /* metatable.__index = metatable */ + luaL_setfuncs(L, flib, 0); /* add file methods to new metatable */ + lua_pop(L, 1); /* pop new metatable */ +} + + +/* +** function to (not) close the standard files stdin, stdout, and stderr +*/ +static int io_noclose (lua_State *L) { + LStream *p = tolstream(L); + p->closef = &io_noclose; /* keep file opened */ + lua_pushnil(L); + lua_pushliteral(L, "cannot close standard file"); + return 2; +} + + +static void createstdfile (lua_State *L, FILE *f, const char *k, + const char *fname) { + LStream *p = newprefile(L); + p->f = f; + p->closef = &io_noclose; + if (k != NULL) { + lua_pushvalue(L, -1); + lua_setfield(L, LUA_REGISTRYINDEX, k); /* add file to registry */ + } + lua_setfield(L, -2, fname); /* add file to module */ +} + + +LUAMOD_API int luaopen_io (lua_State *L) { + luaL_newlib(L, iolib); /* new module */ + createmeta(L); + /* create (and set) default files */ + createstdfile(L, stdin, IO_INPUT, "stdin"); + createstdfile(L, stdout, IO_OUTPUT, "stdout"); + createstdfile(L, stderr, NULL, "stderr"); + return 1; +} + diff --git a/src/lua/llex.c b/src/lua/llex.c new file mode 100644 index 000000000000..b6d9a465fe44 --- /dev/null +++ b/src/lua/llex.c @@ -0,0 +1,568 @@ +/* +** $Id: llex.c,v 2.96.1.1 2017/04/19 17:20:42 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#define llex_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "llex.h" +#include "lobject.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lzio.h" + + + +#define next(ls) (ls->current = zgetc(ls->z)) + + + +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') + + +/* ORDER RESERVED */ +static const char *const luaX_tokens [] = { + "and", "break", "do", "else", "elseif", + "end", "false", "for", "function", "goto", "if", + "in", "local", "nil", "not", "or", "repeat", + "return", "then", "true", "until", "while", + "//", "..", "...", "==", ">=", "<=", "~=", + "<<", ">>", "::", "", + "", "", "", "" +}; + + +#define save_and_next(ls) (save(ls, ls->current), next(ls)) + + +static l_noret lexerror (LexState *ls, const char *msg, int token); + + +static void save (LexState *ls, int c) { + Mbuffer *b = ls->buff; + if (luaZ_bufflen(b) + 1 > luaZ_sizebuffer(b)) { + size_t newsize; + if (luaZ_sizebuffer(b) >= MAX_SIZE/2) + lexerror(ls, "lexical element too long", 0); + newsize = luaZ_sizebuffer(b) * 2; + luaZ_resizebuffer(ls->L, b, newsize); + } + b->buffer[luaZ_bufflen(b)++] = cast(char, c); +} + + +void luaX_init (lua_State *L) { + int i; + TString *e = luaS_newliteral(L, LUA_ENV); /* create env name */ + luaC_fix(L, obj2gco(e)); /* never collect this name */ + for (i=0; iextra = cast_byte(i+1); /* reserved word */ + } +} + + +const char *luaX_token2str (LexState *ls, int token) { + if (token < FIRST_RESERVED) { /* single-byte symbols? */ + lua_assert(token == cast_uchar(token)); + return luaO_pushfstring(ls->L, "'%c'", token); + } + else { + const char *s = luaX_tokens[token - FIRST_RESERVED]; + if (token < TK_EOS) /* fixed format (symbols and reserved words)? */ + return luaO_pushfstring(ls->L, "'%s'", s); + else /* names, strings, and numerals */ + return s; + } +} + + +static const char *txtToken (LexState *ls, int token) { + switch (token) { + case TK_NAME: case TK_STRING: + case TK_FLT: case TK_INT: + save(ls, '\0'); + return luaO_pushfstring(ls->L, "'%s'", luaZ_buffer(ls->buff)); + default: + return luaX_token2str(ls, token); + } +} + + +static l_noret lexerror (LexState *ls, const char *msg, int token) { + msg = luaG_addinfo(ls->L, msg, ls->source, ls->linenumber); + if (token) + luaO_pushfstring(ls->L, "%s near %s", msg, txtToken(ls, token)); + luaD_throw(ls->L, LUA_ERRSYNTAX); +} + + +l_noret luaX_syntaxerror (LexState *ls, const char *msg) { + lexerror(ls, msg, ls->t.token); +} + + +/* +** creates a new string and anchors it in scanner's table so that +** it will not be collected until the end of the compilation +** (by that time it should be anchored somewhere) +*/ +TString *luaX_newstring (LexState *ls, const char *str, size_t l) { + lua_State *L = ls->L; + TValue *o; /* entry for 'str' */ + TString *ts = luaS_newlstr(L, str, l); /* create new string */ + setsvalue2s(L, L->top++, ts); /* temporarily anchor it in stack */ + o = luaH_set(L, ls->h, L->top - 1); + if (ttisnil(o)) { /* not in use yet? */ + /* boolean value does not need GC barrier; + table has no metatable, so it does not need to invalidate cache */ + setbvalue(o, 1); /* t[string] = true */ + luaC_checkGC(L); + } + else { /* string already present */ + ts = tsvalue(keyfromval(o)); /* re-use value previously stored */ + } + L->top--; /* remove string from stack */ + return ts; +} + + +/* +** increment line number and skips newline sequence (any of +** \n, \r, \n\r, or \r\n) +*/ +static void inclinenumber (LexState *ls) { + int old = ls->current; + lua_assert(currIsNewline(ls)); + next(ls); /* skip '\n' or '\r' */ + if (currIsNewline(ls) && ls->current != old) + next(ls); /* skip '\n\r' or '\r\n' */ + if (++ls->linenumber >= MAX_INT) + lexerror(ls, "chunk has too many lines", 0); +} + + +void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, TString *source, + int firstchar) { + ls->t.token = 0; + ls->L = L; + ls->current = firstchar; + ls->lookahead.token = TK_EOS; /* no look-ahead token */ + ls->z = z; + ls->fs = NULL; + ls->linenumber = 1; + ls->lastline = 1; + ls->source = source; + ls->envn = luaS_newliteral(L, LUA_ENV); /* get env name */ + luaZ_resizebuffer(ls->L, ls->buff, LUA_MINBUFFER); /* initialize buffer */ +} + + + +/* +** ======================================================= +** LEXICAL ANALYZER +** ======================================================= +*/ + + +static int check_next1 (LexState *ls, int c) { + if (ls->current == c) { + next(ls); + return 1; + } + else return 0; +} + + +/* +** Check whether current char is in set 'set' (with two chars) and +** saves it +*/ +static int check_next2 (LexState *ls, const char *set) { + lua_assert(set[2] == '\0'); + if (ls->current == set[0] || ls->current == set[1]) { + save_and_next(ls); + return 1; + } + else return 0; +} + + +/* LUA_NUMBER */ +/* +** this function is quite liberal in what it accepts, as 'luaO_str2num' +** will reject ill-formed numerals. +*/ +static int read_numeral (LexState *ls, SemInfo *seminfo) { + TValue obj; + const char *expo = "Ee"; + int first = ls->current; + lua_assert(lisdigit(ls->current)); + save_and_next(ls); + if (first == '0' && check_next2(ls, "xX")) /* hexadecimal? */ + expo = "Pp"; + for (;;) { + if (check_next2(ls, expo)) /* exponent part? */ + check_next2(ls, "-+"); /* optional exponent sign */ + if (lisxdigit(ls->current)) + save_and_next(ls); + else if (ls->current == '.') + save_and_next(ls); + else break; + } + save(ls, '\0'); + if (luaO_str2num(luaZ_buffer(ls->buff), &obj) == 0) /* format error? */ + lexerror(ls, "malformed number", TK_FLT); + if (ttisinteger(&obj)) { + seminfo->i = ivalue(&obj); + return TK_INT; + } + else { + lua_assert(ttisfloat(&obj)); + seminfo->r = fltvalue(&obj); + return TK_FLT; + } +} + + +/* +** reads a sequence '[=*[' or ']=*]', leaving the last bracket. +** If sequence is well formed, return its number of '='s + 2; otherwise, +** return 1 if there is no '='s or 0 otherwise (an unfinished '[==...'). +*/ +static size_t skip_sep (LexState *ls) { + size_t count = 0; + int s = ls->current; + lua_assert(s == '[' || s == ']'); + save_and_next(ls); + while (ls->current == '=') { + save_and_next(ls); + count++; + } + return (ls->current == s) ? count + 2 + : (count == 0) ? 1 + : 0; + +} + + +static void read_long_string (LexState *ls, SemInfo *seminfo, size_t sep) { + int line = ls->linenumber; /* initial line (for error message) */ + save_and_next(ls); /* skip 2nd '[' */ + if (currIsNewline(ls)) /* string starts with a newline? */ + inclinenumber(ls); /* skip it */ + for (;;) { + switch (ls->current) { + case EOZ: { /* error */ + const char *what = (seminfo ? "string" : "comment"); + const char *msg = luaO_pushfstring(ls->L, + "unfinished long %s (starting at line %d)", what, line); + lexerror(ls, msg, TK_EOS); + break; /* to avoid warnings */ + } + case ']': { + if (skip_sep(ls) == sep) { + save_and_next(ls); /* skip 2nd ']' */ + goto endloop; + } + break; + } + case '\n': case '\r': { + save(ls, '\n'); + inclinenumber(ls); + if (!seminfo) luaZ_resetbuffer(ls->buff); /* avoid wasting space */ + break; + } + default: { + if (seminfo) save_and_next(ls); + else next(ls); + } + } + } endloop: + if (seminfo) + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + sep, + luaZ_bufflen(ls->buff) - 2 * sep); +} + + +static void esccheck (LexState *ls, int c, const char *msg) { + if (!c) { + if (ls->current != EOZ) + save_and_next(ls); /* add current to buffer for error message */ + lexerror(ls, msg, TK_STRING); + } +} + + +static int gethexa (LexState *ls) { + save_and_next(ls); + esccheck (ls, lisxdigit(ls->current), "hexadecimal digit expected"); + return luaO_hexavalue(ls->current); +} + + +static int readhexaesc (LexState *ls) { + int r = gethexa(ls); + r = (r << 4) + gethexa(ls); + luaZ_buffremove(ls->buff, 2); /* remove saved chars from buffer */ + return r; +} + + +static unsigned long readutf8esc (LexState *ls) { + unsigned long r; + int i = 4; /* chars to be removed: '\', 'u', '{', and first digit */ + save_and_next(ls); /* skip 'u' */ + esccheck(ls, ls->current == '{', "missing '{'"); + r = gethexa(ls); /* must have at least one digit */ + while ((save_and_next(ls), lisxdigit(ls->current))) { + i++; + r = (r << 4) + luaO_hexavalue(ls->current); + esccheck(ls, r <= 0x10FFFF, "UTF-8 value too large"); + } + esccheck(ls, ls->current == '}', "missing '}'"); + next(ls); /* skip '}' */ + luaZ_buffremove(ls->buff, i); /* remove saved chars from buffer */ + return r; +} + + +static void utf8esc (LexState *ls) { + char buff[UTF8BUFFSZ]; + int n = luaO_utf8esc(buff, readutf8esc(ls)); + for (; n > 0; n--) /* add 'buff' to string */ + save(ls, buff[UTF8BUFFSZ - n]); +} + + +static int readdecesc (LexState *ls) { + int i; + int r = 0; /* result accumulator */ + for (i = 0; i < 3 && lisdigit(ls->current); i++) { /* read up to 3 digits */ + r = 10*r + ls->current - '0'; + save_and_next(ls); + } + esccheck(ls, r <= UCHAR_MAX, "decimal escape too large"); + luaZ_buffremove(ls->buff, i); /* remove read digits from buffer */ + return r; +} + + +static void read_string (LexState *ls, int del, SemInfo *seminfo) { + save_and_next(ls); /* keep delimiter (for error messages) */ + while (ls->current != del) { + switch (ls->current) { + case EOZ: + lexerror(ls, "unfinished string", TK_EOS); + break; /* to avoid warnings */ + case '\n': + case '\r': + lexerror(ls, "unfinished string", TK_STRING); + break; /* to avoid warnings */ + case '\\': { /* escape sequences */ + int c; /* final character to be saved */ + save_and_next(ls); /* keep '\\' for error messages */ + switch (ls->current) { + case 'a': c = '\a'; goto read_save; + case 'b': c = '\b'; goto read_save; + case 'f': c = '\f'; goto read_save; + case 'n': c = '\n'; goto read_save; + case 'r': c = '\r'; goto read_save; + case 't': c = '\t'; goto read_save; + case 'v': c = '\v'; goto read_save; + case 'x': c = readhexaesc(ls); goto read_save; + case 'u': utf8esc(ls); goto no_save; + case '\n': case '\r': + inclinenumber(ls); c = '\n'; goto only_save; + case '\\': case '\"': case '\'': + c = ls->current; goto read_save; + case EOZ: goto no_save; /* will raise an error next loop */ + case 'z': { /* zap following span of spaces */ + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + next(ls); /* skip the 'z' */ + while (lisspace(ls->current)) { + if (currIsNewline(ls)) inclinenumber(ls); + else next(ls); + } + goto no_save; + } + default: { + esccheck(ls, lisdigit(ls->current), "invalid escape sequence"); + c = readdecesc(ls); /* digital escape '\ddd' */ + goto only_save; + } + } + read_save: + next(ls); + /* go through */ + only_save: + luaZ_buffremove(ls->buff, 1); /* remove '\\' */ + save(ls, c); + /* go through */ + no_save: break; + } + default: + save_and_next(ls); + } + } + save_and_next(ls); /* skip delimiter */ + seminfo->ts = luaX_newstring(ls, luaZ_buffer(ls->buff) + 1, + luaZ_bufflen(ls->buff) - 2); +} + + +static int llex (LexState *ls, SemInfo *seminfo) { + luaZ_resetbuffer(ls->buff); + for (;;) { + switch (ls->current) { + case '\n': case '\r': { /* line breaks */ + inclinenumber(ls); + break; + } + case ' ': case '\f': case '\t': case '\v': { /* spaces */ + next(ls); + break; + } + case '-': { /* '-' or '--' (comment) */ + next(ls); + if (ls->current != '-') return '-'; + /* else is a comment */ + next(ls); + if (ls->current == '[') { /* long comment? */ + size_t sep = skip_sep(ls); + luaZ_resetbuffer(ls->buff); /* 'skip_sep' may dirty the buffer */ + if (sep >= 2) { + read_long_string(ls, NULL, sep); /* skip long comment */ + luaZ_resetbuffer(ls->buff); /* previous call may dirty the buff. */ + break; + } + } + /* else short comment */ + while (!currIsNewline(ls) && ls->current != EOZ) + next(ls); /* skip until end of line (or end of file) */ + break; + } + case '[': { /* long string or simply '[' */ + size_t sep = skip_sep(ls); + if (sep >= 2) { + read_long_string(ls, seminfo, sep); + return TK_STRING; + } + else if (sep == 0) /* '[=...' missing second bracket */ + lexerror(ls, "invalid long string delimiter", TK_STRING); + return '['; + } + case '=': { + next(ls); + if (check_next1(ls, '=')) return TK_EQ; + else return '='; + } + case '<': { + next(ls); + if (check_next1(ls, '=')) return TK_LE; + else if (check_next1(ls, '<')) return TK_SHL; + else return '<'; + } + case '>': { + next(ls); + if (check_next1(ls, '=')) return TK_GE; + else if (check_next1(ls, '>')) return TK_SHR; + else return '>'; + } + case '/': { + next(ls); + if (check_next1(ls, '/')) return TK_IDIV; + else return '/'; + } + case '~': { + next(ls); + if (check_next1(ls, '=')) return TK_NE; + else return '~'; + } + case ':': { + next(ls); + if (check_next1(ls, ':')) return TK_DBCOLON; + else return ':'; + } + case '"': case '\'': { /* short literal strings */ + read_string(ls, ls->current, seminfo); + return TK_STRING; + } + case '.': { /* '.', '..', '...', or number */ + save_and_next(ls); + if (check_next1(ls, '.')) { + if (check_next1(ls, '.')) + return TK_DOTS; /* '...' */ + else return TK_CONCAT; /* '..' */ + } + else if (!lisdigit(ls->current)) return '.'; + else return read_numeral(ls, seminfo); + } + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': { + return read_numeral(ls, seminfo); + } + case EOZ: { + return TK_EOS; + } + default: { + if (lislalpha(ls->current)) { /* identifier or reserved word? */ + TString *ts; + do { + save_and_next(ls); + } while (lislalnum(ls->current)); + ts = luaX_newstring(ls, luaZ_buffer(ls->buff), + luaZ_bufflen(ls->buff)); + seminfo->ts = ts; + if (isreserved(ts)) /* reserved word? */ + return ts->extra - 1 + FIRST_RESERVED; + else { + return TK_NAME; + } + } + else { /* single-char tokens (+ - / ...) */ + int c = ls->current; + next(ls); + return c; + } + } + } + } +} + + +void luaX_next (LexState *ls) { + ls->lastline = ls->linenumber; + if (ls->lookahead.token != TK_EOS) { /* is there a look-ahead token? */ + ls->t = ls->lookahead; /* use this one */ + ls->lookahead.token = TK_EOS; /* and discharge it */ + } + else + ls->t.token = llex(ls, &ls->t.seminfo); /* read next token */ +} + + +int luaX_lookahead (LexState *ls) { + lua_assert(ls->lookahead.token == TK_EOS); + ls->lookahead.token = llex(ls, &ls->lookahead.seminfo); + return ls->lookahead.token; +} + diff --git a/src/lua/llex.h b/src/lua/llex.h new file mode 100644 index 000000000000..2ed0af66a48f --- /dev/null +++ b/src/lua/llex.h @@ -0,0 +1,85 @@ +/* +** $Id: llex.h,v 1.79.1.1 2017/04/19 17:20:42 roberto Exp $ +** Lexical Analyzer +** See Copyright Notice in lua.h +*/ + +#ifndef llex_h +#define llex_h + +#include "lobject.h" +#include "lzio.h" + + +#define FIRST_RESERVED 257 + + +#if !defined(LUA_ENV) +#define LUA_ENV "_ENV" +#endif + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER RESERVED" +*/ +enum RESERVED { + /* terminal symbols denoted by reserved words */ + TK_AND = FIRST_RESERVED, TK_BREAK, + TK_DO, TK_ELSE, TK_ELSEIF, TK_END, TK_FALSE, TK_FOR, TK_FUNCTION, + TK_GOTO, TK_IF, TK_IN, TK_LOCAL, TK_NIL, TK_NOT, TK_OR, TK_REPEAT, + TK_RETURN, TK_THEN, TK_TRUE, TK_UNTIL, TK_WHILE, + /* other terminal symbols */ + TK_IDIV, TK_CONCAT, TK_DOTS, TK_EQ, TK_GE, TK_LE, TK_NE, + TK_SHL, TK_SHR, + TK_DBCOLON, TK_EOS, + TK_FLT, TK_INT, TK_NAME, TK_STRING +}; + +/* number of reserved words */ +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) + + +typedef union { + lua_Number r; + lua_Integer i; + TString *ts; +} SemInfo; /* semantics information */ + + +typedef struct Token { + int token; + SemInfo seminfo; +} Token; + + +/* state of the lexer plus state of the parser when shared by all + functions */ +typedef struct LexState { + int current; /* current character (charint) */ + int linenumber; /* input line counter */ + int lastline; /* line of last token 'consumed' */ + Token t; /* current token */ + Token lookahead; /* look ahead token */ + struct FuncState *fs; /* current function (parser) */ + struct lua_State *L; + ZIO *z; /* input stream */ + Mbuffer *buff; /* buffer for tokens */ + Table *h; /* to avoid collection/reuse strings */ + struct Dyndata *dyd; /* dynamic structures used by the parser */ + TString *source; /* current source name */ + TString *envn; /* environment variable name */ +} LexState; + + +LUAI_FUNC void luaX_init (lua_State *L); +LUAI_FUNC void luaX_setinput (lua_State *L, LexState *ls, ZIO *z, + TString *source, int firstchar); +LUAI_FUNC TString *luaX_newstring (LexState *ls, const char *str, size_t l); +LUAI_FUNC void luaX_next (LexState *ls); +LUAI_FUNC int luaX_lookahead (LexState *ls); +LUAI_FUNC l_noret luaX_syntaxerror (LexState *ls, const char *s); +LUAI_FUNC const char *luaX_token2str (LexState *ls, int token); + + +#endif diff --git a/src/lua/llimits.h b/src/lua/llimits.h new file mode 100644 index 000000000000..d1036f6bc8d4 --- /dev/null +++ b/src/lua/llimits.h @@ -0,0 +1,323 @@ +/* +** $Id: llimits.h,v 1.141.1.1 2017/04/19 17:20:42 roberto Exp $ +** Limits, basic types, and some other 'installation-dependent' definitions +** See Copyright Notice in lua.h +*/ + +#ifndef llimits_h +#define llimits_h + + +#include +#include + + +#include "lua.h" + +/* +** 'lu_mem' and 'l_mem' are unsigned/signed integers big enough to count +** the total memory used by Lua (in bytes). Usually, 'size_t' and +** 'ptrdiff_t' should work, but we use 'long' for 16-bit machines. +*/ +#if defined(LUAI_MEM) /* { external definitions? */ +typedef LUAI_UMEM lu_mem; +typedef LUAI_MEM l_mem; +#elif LUAI_BITSINT >= 32 /* }{ */ +typedef size_t lu_mem; +typedef ptrdiff_t l_mem; +#else /* 16-bit ints */ /* }{ */ +typedef unsigned long lu_mem; +typedef long l_mem; +#endif /* } */ + + +/* chars used as small naturals (so that 'char' is reserved for characters) */ +typedef unsigned char lu_byte; + + +/* maximum value for size_t */ +#define MAX_SIZET ((size_t)(~(size_t)0)) + +/* maximum size visible for Lua (must be representable in a lua_Integer */ +#define MAX_SIZE (sizeof(size_t) < sizeof(lua_Integer) ? MAX_SIZET \ + : (size_t)(LUA_MAXINTEGER)) + + +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)) + +#define MAX_LMEM ((l_mem)(MAX_LUMEM >> 1)) + + +#define MAX_INT INT_MAX /* maximum value of an int */ + + +/* +** conversion of pointer to unsigned integer: +** this is for hashing only; there is no problem if the integer +** cannot hold the whole pointer value +*/ +#define point2uint(p) ((unsigned int)((size_t)(p) & UINT_MAX)) + + + +/* type to ensure maximum alignment */ +#if defined(LUAI_USER_ALIGNMENT_T) +typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; +#else +typedef union { + lua_Number n; + double u; + void *s; + lua_Integer i; + long l; +} L_Umaxalign; +#endif + + + +/* types of 'usual argument conversions' for lua_Number and lua_Integer */ +typedef LUAI_UACNUMBER l_uacNumber; +typedef LUAI_UACINT l_uacInt; + + +/* internal assertions for in-house debugging */ +#if defined(lua_assert) +#define check_exp(c,e) (lua_assert(c), (e)) +/* to avoid problems with conditions too long */ +#define lua_longassert(c) ((c) ? (void)0 : lua_assert(0)) +#else +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define lua_longassert(c) ((void)0) +#endif + +/* +** assertion for checking API calls +*/ +#if !defined(luai_apicheck) +#define luai_apicheck(l,e) lua_assert(e) +#endif + +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) + + +/* macro to avoid warnings about unused variables */ +#if !defined(UNUSED) +#define UNUSED(x) ((void)(x)) +#endif + + +/* type casts (a macro highlights casts in the code) */ +#define cast(t, exp) ((t)(exp)) + +#define cast_void(i) cast(void, (i)) +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) +#define cast_uchar(i) cast(unsigned char, (i)) + + +/* cast a signed lua_Integer to lua_Unsigned */ +#if !defined(l_castS2U) +#define l_castS2U(i) ((lua_Unsigned)(i)) +#endif + +/* +** cast a lua_Unsigned to a signed lua_Integer; this cast is +** not strict ISO C, but two-complement architectures should +** work fine. +*/ +#if !defined(l_castU2S) +#define l_castU2S(i) ((lua_Integer)(i)) +#endif + + +/* +** non-return type +*/ +#if defined(__GNUC__) +#define l_noret void __attribute__((noreturn)) +#elif defined(_MSC_VER) && _MSC_VER >= 1200 +#define l_noret void __declspec(noreturn) +#else +#define l_noret void +#endif + + + +/* +** maximum depth for nested C calls and syntactical nested non-terminals +** in a program. (Value must fit in an unsigned short int.) +*/ +#if !defined(LUAI_MAXCCALLS) +#define LUAI_MAXCCALLS 200 +#endif + + + +/* +** type for virtual-machine instructions; +** must be an unsigned with (at least) 4 bytes (see details in lopcodes.h) +*/ +#if LUAI_BITSINT >= 32 +typedef unsigned int Instruction; +#else +typedef unsigned long Instruction; +#endif + + + +/* +** Maximum length for short strings, that is, strings that are +** internalized. (Cannot be smaller than reserved words or tags for +** metamethods, as these strings must be internalized; +** #("function") = 8, #("__newindex") = 10.) +*/ +#if !defined(LUAI_MAXSHORTLEN) +#define LUAI_MAXSHORTLEN 40 +#endif + + +/* +** Initial size for the string table (must be power of 2). +** The Lua core alone registers ~50 strings (reserved words + +** metaevent keys + a few others). Libraries would typically add +** a few dozens more. +*/ +#if !defined(MINSTRTABSIZE) +#define MINSTRTABSIZE 128 +#endif + + +/* +** Size of cache for strings in the API. 'N' is the number of +** sets (better be a prime) and "M" is the size of each set (M == 1 +** makes a direct cache.) +*/ +#if !defined(STRCACHE_N) +#define STRCACHE_N 53 +#define STRCACHE_M 2 +#endif + + +/* minimum size for string buffer */ +#if !defined(LUA_MINBUFFER) +#define LUA_MINBUFFER 32 +#endif + + +/* +** macros that are executed whenever program enters the Lua core +** ('lua_lock') and leaves the core ('lua_unlock') +*/ +#if !defined(lua_lock) +#define lua_lock(L) ((void) 0) +#define lua_unlock(L) ((void) 0) +#endif + +/* +** macro executed during Lua functions at points where the +** function can yield. +*/ +#if !defined(luai_threadyield) +#define luai_threadyield(L) {lua_unlock(L); lua_lock(L);} +#endif + + +/* +** these macros allow user-specific actions on threads when you defined +** LUAI_EXTRASPACE and need to do something extra when a thread is +** created/deleted/resumed/yielded. +*/ +#if !defined(luai_userstateopen) +#define luai_userstateopen(L) ((void)L) +#endif + +#if !defined(luai_userstateclose) +#define luai_userstateclose(L) ((void)L) +#endif + +#if !defined(luai_userstatethread) +#define luai_userstatethread(L,L1) ((void)L) +#endif + +#if !defined(luai_userstatefree) +#define luai_userstatefree(L,L1) ((void)L) +#endif + +#if !defined(luai_userstateresume) +#define luai_userstateresume(L,n) ((void)L) +#endif + +#if !defined(luai_userstateyield) +#define luai_userstateyield(L,n) ((void)L) +#endif + + + +/* +** The luai_num* macros define the primitive operations over numbers. +*/ + +/* floor division (defined as 'floor(a/b)') */ +#if !defined(luai_numidiv) +#define luai_numidiv(L,a,b) ((void)L, l_floor(luai_numdiv(L,a,b))) +#endif + +/* float division */ +#if !defined(luai_numdiv) +#define luai_numdiv(L,a,b) ((a)/(b)) +#endif + +/* +** modulo: defined as 'a - floor(a/b)*b'; this definition gives NaN when +** 'b' is huge, but the result should be 'a'. 'fmod' gives the result of +** 'a - trunc(a/b)*b', and therefore must be corrected when 'trunc(a/b) +** ~= floor(a/b)'. That happens when the division has a non-integer +** negative result, which is equivalent to the test below. +*/ +#if !defined(luai_nummod) +#define luai_nummod(L,a,b,m) \ + { (m) = l_mathop(fmod)(a,b); if ((m)*(b) < 0) (m) += (b); } +#endif + +/* exponentiation */ +#if !defined(luai_numpow) +#define luai_numpow(L,a,b) ((void)L, l_mathop(pow)(a,b)) +#endif + +/* the others are quite standard operations */ +#if !defined(luai_numadd) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(a,b) ((a)<(b)) +#define luai_numle(a,b) ((a)<=(b)) +#define luai_numisnan(a) (!luai_numeq((a), (a))) +#endif + + + + + +/* +** macro to control inclusion of some hard tests on stack reallocation +*/ +#if !defined(HARDSTACKTESTS) +#define condmovestack(L,pre,pos) ((void)0) +#else +/* realloc stack keeping its size */ +#define condmovestack(L,pre,pos) \ + { int sz_ = (L)->stacksize; pre; luaD_reallocstack((L), sz_); pos; } +#endif + +#if !defined(HARDMEMTESTS) +#define condchangemem(L,pre,pos) ((void)0) +#else +#define condchangemem(L,pre,pos) \ + { if (G(L)->gcrunning) { pre; luaC_fullgc(L, 0); pos; } } +#endif + +#endif diff --git a/src/lua/lmathlib.c b/src/lua/lmathlib.c new file mode 100644 index 000000000000..7ef7e593fd38 --- /dev/null +++ b/src/lua/lmathlib.c @@ -0,0 +1,410 @@ +/* +** $Id: lmathlib.c,v 1.119.1.1 2017/04/19 17:20:42 roberto Exp $ +** Standard mathematical library +** See Copyright Notice in lua.h +*/ + +#define lmathlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +#undef PI +#define PI (l_mathop(3.141592653589793238462643383279502884)) + + +#if !defined(l_rand) /* { */ +#if defined(LUA_USE_POSIX) +#define l_rand() random() +#define l_srand(x) srandom(x) +#define L_RANDMAX 2147483647 /* (2^31 - 1), following POSIX */ +#else +#define l_rand() rand() +#define l_srand(x) srand(x) +#define L_RANDMAX RAND_MAX +#endif +#endif /* } */ + + +static int math_abs (lua_State *L) { + if (lua_isinteger(L, 1)) { + lua_Integer n = lua_tointeger(L, 1); + if (n < 0) n = (lua_Integer)(0u - (lua_Unsigned)n); + lua_pushinteger(L, n); + } + else + lua_pushnumber(L, l_mathop(fabs)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sin (lua_State *L) { + lua_pushnumber(L, l_mathop(sin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_cos (lua_State *L) { + lua_pushnumber(L, l_mathop(cos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tan (lua_State *L) { + lua_pushnumber(L, l_mathop(tan)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_asin (lua_State *L) { + lua_pushnumber(L, l_mathop(asin)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_acos (lua_State *L) { + lua_pushnumber(L, l_mathop(acos)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_atan (lua_State *L) { + lua_Number y = luaL_checknumber(L, 1); + lua_Number x = luaL_optnumber(L, 2, 1); + lua_pushnumber(L, l_mathop(atan2)(y, x)); + return 1; +} + + +static int math_toint (lua_State *L) { + int valid; + lua_Integer n = lua_tointegerx(L, 1, &valid); + if (valid) + lua_pushinteger(L, n); + else { + luaL_checkany(L, 1); + lua_pushnil(L); /* value is not convertible to integer */ + } + return 1; +} + + +static void pushnumint (lua_State *L, lua_Number d) { + lua_Integer n; + if (lua_numbertointeger(d, &n)) /* does 'd' fit in an integer? */ + lua_pushinteger(L, n); /* result is integer */ + else + lua_pushnumber(L, d); /* result is float */ +} + + +static int math_floor (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own floor */ + else { + lua_Number d = l_mathop(floor)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + +static int math_ceil (lua_State *L) { + if (lua_isinteger(L, 1)) + lua_settop(L, 1); /* integer is its own ceil */ + else { + lua_Number d = l_mathop(ceil)(luaL_checknumber(L, 1)); + pushnumint(L, d); + } + return 1; +} + + +static int math_fmod (lua_State *L) { + if (lua_isinteger(L, 1) && lua_isinteger(L, 2)) { + lua_Integer d = lua_tointeger(L, 2); + if ((lua_Unsigned)d + 1u <= 1u) { /* special cases: -1 or 0 */ + luaL_argcheck(L, d != 0, 2, "zero"); + lua_pushinteger(L, 0); /* avoid overflow with 0x80000... / -1 */ + } + else + lua_pushinteger(L, lua_tointeger(L, 1) % d); + } + else + lua_pushnumber(L, l_mathop(fmod)(luaL_checknumber(L, 1), + luaL_checknumber(L, 2))); + return 1; +} + + +/* +** next function does not use 'modf', avoiding problems with 'double*' +** (which is not compatible with 'float*') when lua_Number is not +** 'double'. +*/ +static int math_modf (lua_State *L) { + if (lua_isinteger(L ,1)) { + lua_settop(L, 1); /* number is its own integer part */ + lua_pushnumber(L, 0); /* no fractional part */ + } + else { + lua_Number n = luaL_checknumber(L, 1); + /* integer part (rounds toward zero) */ + lua_Number ip = (n < 0) ? l_mathop(ceil)(n) : l_mathop(floor)(n); + pushnumint(L, ip); + /* fractional part (test needed for inf/-inf) */ + lua_pushnumber(L, (n == ip) ? l_mathop(0.0) : (n - ip)); + } + return 2; +} + + +static int math_sqrt (lua_State *L) { + lua_pushnumber(L, l_mathop(sqrt)(luaL_checknumber(L, 1))); + return 1; +} + + +static int math_ult (lua_State *L) { + lua_Integer a = luaL_checkinteger(L, 1); + lua_Integer b = luaL_checkinteger(L, 2); + lua_pushboolean(L, (lua_Unsigned)a < (lua_Unsigned)b); + return 1; +} + +static int math_log (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number res; + if (lua_isnoneornil(L, 2)) + res = l_mathop(log)(x); + else { + lua_Number base = luaL_checknumber(L, 2); +#if !defined(LUA_USE_C89) + if (base == l_mathop(2.0)) + res = l_mathop(log2)(x); else +#endif + if (base == l_mathop(10.0)) + res = l_mathop(log10)(x); + else + res = l_mathop(log)(x)/l_mathop(log)(base); + } + lua_pushnumber(L, res); + return 1; +} + +static int math_exp (lua_State *L) { + lua_pushnumber(L, l_mathop(exp)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_deg (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1) * (l_mathop(180.0) / PI)); + return 1; +} + +static int math_rad (lua_State *L) { + lua_pushnumber(L, luaL_checknumber(L, 1) * (PI / l_mathop(180.0))); + return 1; +} + + +static int math_min (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int imin = 1; /* index of current minimum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, i, imin, LUA_OPLT)) + imin = i; + } + lua_pushvalue(L, imin); + return 1; +} + + +static int math_max (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + int imax = 1; /* index of current maximum value */ + int i; + luaL_argcheck(L, n >= 1, 1, "value expected"); + for (i = 2; i <= n; i++) { + if (lua_compare(L, imax, i, LUA_OPLT)) + imax = i; + } + lua_pushvalue(L, imax); + return 1; +} + +/* +** This function uses 'double' (instead of 'lua_Number') to ensure that +** all bits from 'l_rand' can be represented, and that 'RANDMAX + 1.0' +** will keep full precision (ensuring that 'r' is always less than 1.0.) +*/ +static int math_random (lua_State *L) { + lua_Integer low, up; + double r = (double)l_rand() * (1.0 / ((double)L_RANDMAX + 1.0)); + switch (lua_gettop(L)) { /* check number of arguments */ + case 0: { /* no arguments */ + lua_pushnumber(L, (lua_Number)r); /* Number between 0 and 1 */ + return 1; + } + case 1: { /* only upper limit */ + low = 1; + up = luaL_checkinteger(L, 1); + break; + } + case 2: { /* lower and upper limits */ + low = luaL_checkinteger(L, 1); + up = luaL_checkinteger(L, 2); + break; + } + default: return luaL_error(L, "wrong number of arguments"); + } + /* random integer in the interval [low, up] */ + luaL_argcheck(L, low <= up, 1, "interval is empty"); + luaL_argcheck(L, low >= 0 || up <= LUA_MAXINTEGER + low, 1, + "interval too large"); + r *= (double)(up - low) + 1.0; + lua_pushinteger(L, (lua_Integer)r + low); + return 1; +} + + +static int math_randomseed (lua_State *L) { + l_srand((unsigned int)(lua_Integer)luaL_checknumber(L, 1)); + (void)l_rand(); /* discard first value to avoid undesirable correlations */ + return 0; +} + + +static int math_type (lua_State *L) { + if (lua_type(L, 1) == LUA_TNUMBER) { + if (lua_isinteger(L, 1)) + lua_pushliteral(L, "integer"); + else + lua_pushliteral(L, "float"); + } + else { + luaL_checkany(L, 1); + lua_pushnil(L); + } + return 1; +} + + +/* +** {================================================================== +** Deprecated functions (for compatibility only) +** =================================================================== +*/ +#if defined(LUA_COMPAT_MATHLIB) + +static int math_cosh (lua_State *L) { + lua_pushnumber(L, l_mathop(cosh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_sinh (lua_State *L) { + lua_pushnumber(L, l_mathop(sinh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_tanh (lua_State *L) { + lua_pushnumber(L, l_mathop(tanh)(luaL_checknumber(L, 1))); + return 1; +} + +static int math_pow (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + lua_Number y = luaL_checknumber(L, 2); + lua_pushnumber(L, l_mathop(pow)(x, y)); + return 1; +} + +static int math_frexp (lua_State *L) { + int e; + lua_pushnumber(L, l_mathop(frexp)(luaL_checknumber(L, 1), &e)); + lua_pushinteger(L, e); + return 2; +} + +static int math_ldexp (lua_State *L) { + lua_Number x = luaL_checknumber(L, 1); + int ep = (int)luaL_checkinteger(L, 2); + lua_pushnumber(L, l_mathop(ldexp)(x, ep)); + return 1; +} + +static int math_log10 (lua_State *L) { + lua_pushnumber(L, l_mathop(log10)(luaL_checknumber(L, 1))); + return 1; +} + +#endif +/* }================================================================== */ + + + +static const luaL_Reg mathlib[] = { + {"abs", math_abs}, + {"acos", math_acos}, + {"asin", math_asin}, + {"atan", math_atan}, + {"ceil", math_ceil}, + {"cos", math_cos}, + {"deg", math_deg}, + {"exp", math_exp}, + {"tointeger", math_toint}, + {"floor", math_floor}, + {"fmod", math_fmod}, + {"ult", math_ult}, + {"log", math_log}, + {"max", math_max}, + {"min", math_min}, + {"modf", math_modf}, + {"rad", math_rad}, + {"random", math_random}, + {"randomseed", math_randomseed}, + {"sin", math_sin}, + {"sqrt", math_sqrt}, + {"tan", math_tan}, + {"type", math_type}, +#if defined(LUA_COMPAT_MATHLIB) + {"atan2", math_atan}, + {"cosh", math_cosh}, + {"sinh", math_sinh}, + {"tanh", math_tanh}, + {"pow", math_pow}, + {"frexp", math_frexp}, + {"ldexp", math_ldexp}, + {"log10", math_log10}, +#endif + /* placeholders */ + {"pi", NULL}, + {"huge", NULL}, + {"maxinteger", NULL}, + {"mininteger", NULL}, + {NULL, NULL} +}; + + +/* +** Open math library +*/ +LUAMOD_API int luaopen_math (lua_State *L) { + luaL_newlib(L, mathlib); + lua_pushnumber(L, PI); + lua_setfield(L, -2, "pi"); + lua_pushnumber(L, (lua_Number)HUGE_VAL); + lua_setfield(L, -2, "huge"); + lua_pushinteger(L, LUA_MAXINTEGER); + lua_setfield(L, -2, "maxinteger"); + lua_pushinteger(L, LUA_MININTEGER); + lua_setfield(L, -2, "mininteger"); + return 1; +} + diff --git a/src/lua/lmem.c b/src/lua/lmem.c new file mode 100644 index 000000000000..0241cc3bac0d --- /dev/null +++ b/src/lua/lmem.c @@ -0,0 +1,100 @@ +/* +** $Id: lmem.c,v 1.91.1.1 2017/04/19 17:20:42 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#define lmem_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" + + + +/* +** About the realloc function: +** void * frealloc (void *ud, void *ptr, size_t osize, size_t nsize); +** ('osize' is the old size, 'nsize' is the new size) +** +** * frealloc(ud, NULL, x, s) creates a new block of size 's' (no +** matter 'x'). +** +** * frealloc(ud, p, x, 0) frees the block 'p' +** (in this specific case, frealloc must return NULL); +** particularly, frealloc(ud, NULL, 0, 0) does nothing +** (which is equivalent to free(NULL) in ISO C) +** +** frealloc returns NULL if it cannot create or reallocate the area +** (any reallocation to an equal or smaller size cannot fail!) +*/ + + + +#define MINSIZEARRAY 4 + + +void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, + int limit, const char *what) { + void *newblock; + int newsize; + if (*size >= limit/2) { /* cannot double it? */ + if (*size >= limit) /* cannot grow even a little? */ + luaG_runerror(L, "too many %s (limit is %d)", what, limit); + newsize = limit; /* still have at least one free place */ + } + else { + newsize = (*size)*2; + if (newsize < MINSIZEARRAY) + newsize = MINSIZEARRAY; /* minimum size */ + } + newblock = luaM_reallocv(L, block, *size, newsize, size_elems); + *size = newsize; /* update only when everything else is OK */ + return newblock; +} + + +l_noret luaM_toobig (lua_State *L) { + luaG_runerror(L, "memory allocation error: block too big"); +} + + + +/* +** generic allocation routine. +*/ +void *luaM_realloc_ (lua_State *L, void *block, size_t osize, size_t nsize) { + void *newblock; + global_State *g = G(L); + size_t realosize = (block) ? osize : 0; + lua_assert((realosize == 0) == (block == NULL)); +#if defined(HARDMEMTESTS) + if (nsize > realosize && g->gcrunning) + luaC_fullgc(L, 1); /* force a GC whenever possible */ +#endif + newblock = (*g->frealloc)(g->ud, block, osize, nsize); + if (newblock == NULL && nsize > 0) { + lua_assert(nsize > realosize); /* cannot fail when shrinking a block */ + if (g->version) { /* is state fully built? */ + luaC_fullgc(L, 1); /* try to free some memory... */ + newblock = (*g->frealloc)(g->ud, block, osize, nsize); /* try again */ + } + if (newblock == NULL) + luaD_throw(L, LUA_ERRMEM); + } + lua_assert((nsize == 0) == (newblock == NULL)); + g->GCdebt = (g->GCdebt + nsize) - realosize; + return newblock; +} + diff --git a/src/lua/lmem.h b/src/lua/lmem.h new file mode 100644 index 000000000000..357b1e43e7f5 --- /dev/null +++ b/src/lua/lmem.h @@ -0,0 +1,69 @@ +/* +** $Id: lmem.h,v 1.43.1.1 2017/04/19 17:20:42 roberto Exp $ +** Interface to Memory Manager +** See Copyright Notice in lua.h +*/ + +#ifndef lmem_h +#define lmem_h + + +#include + +#include "llimits.h" +#include "lua.h" + + +/* +** This macro reallocs a vector 'b' from 'on' to 'n' elements, where +** each element has size 'e'. In case of arithmetic overflow of the +** product 'n'*'e', it raises an error (calling 'luaM_toobig'). Because +** 'e' is always constant, it avoids the runtime division MAX_SIZET/(e). +** +** (The macro is somewhat complex to avoid warnings: The 'sizeof' +** comparison avoids a runtime comparison when overflow cannot occur. +** The compiler should be able to optimize the real test by itself, but +** when it does it, it may give a warning about "comparison is always +** false due to limited range of data type"; the +1 tricks the compiler, +** avoiding this warning but also this optimization.) +*/ +#define luaM_reallocv(L,b,on,n,e) \ + (((sizeof(n) >= sizeof(size_t) && cast(size_t, (n)) + 1 > MAX_SIZET/(e)) \ + ? luaM_toobig(L) : cast_void(0)) , \ + luaM_realloc_(L, (b), (on)*(e), (n)*(e))) + +/* +** Arrays of chars do not need any test +*/ +#define luaM_reallocvchar(L,b,on,n) \ + cast(char *, luaM_realloc_(L, (b), (on)*sizeof(char), (n)*sizeof(char))) + +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freearray(L, b, n) luaM_realloc_(L, (b), (n)*sizeof(*(b)), 0) + +#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_newvector(L,n,t) \ + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + +#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) + +#define luaM_growvector(L,v,nelems,size,t,limit,e) \ + if ((nelems)+1 > (size)) \ + ((v)=cast(t *, luaM_growaux_(L,v,&(size),sizeof(t),limit,e))) + +#define luaM_reallocvector(L, v,oldn,n,t) \ + ((v)=cast(t *, luaM_reallocv(L, v, oldn, n, sizeof(t)))) + +LUAI_FUNC l_noret luaM_toobig (lua_State *L); + +/* not to be called directly */ +LUAI_FUNC void *luaM_realloc_ (lua_State *L, void *block, size_t oldsize, + size_t size); +LUAI_FUNC void *luaM_growaux_ (lua_State *L, void *block, int *size, + size_t size_elem, int limit, + const char *what); + +#endif + diff --git a/src/lua/loadlib.c b/src/lua/loadlib.c new file mode 100644 index 000000000000..45f44d3225a1 --- /dev/null +++ b/src/lua/loadlib.c @@ -0,0 +1,790 @@ +/* +** $Id: loadlib.c,v 1.130.1.1 2017/04/19 17:20:42 roberto Exp $ +** Dynamic library loader for Lua +** See Copyright Notice in lua.h +** +** This module contains an implementation of loadlib for Unix systems +** that have dlfcn, an implementation for Windows, and a stub for other +** systems. +*/ + +#define loadlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** LUA_IGMARK is a mark to ignore all before it when building the +** luaopen_ function name. +*/ +#if !defined (LUA_IGMARK) +#define LUA_IGMARK "-" +#endif + + +/* +** LUA_CSUBSEP is the character that replaces dots in submodule names +** when searching for a C loader. +** LUA_LSUBSEP is the character that replaces dots in submodule names +** when searching for a Lua loader. +*/ +#if !defined(LUA_CSUBSEP) +#define LUA_CSUBSEP LUA_DIRSEP +#endif + +#if !defined(LUA_LSUBSEP) +#define LUA_LSUBSEP LUA_DIRSEP +#endif + + +/* prefix for open functions in C libraries */ +#define LUA_POF "luaopen_" + +/* separator for open functions in C libraries */ +#define LUA_OFSEP "_" + + +/* +** unique key for table in the registry that keeps handles +** for all loaded C libraries +*/ +static const int CLIBS = 0; + +#define LIB_FAIL "open" + + +#define setprogdir(L) ((void)0) + + +/* +** system-dependent functions +*/ + +/* +** unload library 'lib' +*/ +static void lsys_unloadlib (void *lib); + +/* +** load C library in file 'path'. If 'seeglb', load with all names in +** the library global. +** Returns the library; in case of error, returns NULL plus an +** error string in the stack. +*/ +static void *lsys_load (lua_State *L, const char *path, int seeglb); + +/* +** Try to find a function named 'sym' in library 'lib'. +** Returns the function; in case of error, returns NULL plus an +** error string in the stack. +*/ +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym); + + + + +#if defined(LUA_USE_DLOPEN) /* { */ +/* +** {======================================================================== +** This is an implementation of loadlib based on the dlfcn interface. +** The dlfcn interface is available in Linux, SunOS, Solaris, IRIX, FreeBSD, +** NetBSD, AIX 4.2, HPUX 11, and probably most other Unix flavors, at least +** as an emulation layer on top of native functions. +** ========================================================================= +*/ + +#include + +/* +** Macro to convert pointer-to-void* to pointer-to-function. This cast +** is undefined according to ISO C, but POSIX assumes that it works. +** (The '__extension__' in gnu compilers is only to avoid warnings.) +*/ +#if defined(__GNUC__) +#define cast_func(p) (__extension__ (lua_CFunction)(p)) +#else +#define cast_func(p) ((lua_CFunction)(p)) +#endif + + +static void lsys_unloadlib (void *lib) { + dlclose(lib); +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + void *lib = dlopen(path, RTLD_NOW | (seeglb ? RTLD_GLOBAL : RTLD_LOCAL)); + if (lib == NULL) lua_pushstring(L, dlerror()); + return lib; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = cast_func(dlsym(lib, sym)); + if (f == NULL) lua_pushstring(L, dlerror()); + return f; +} + +/* }====================================================== */ + + + +#elif defined(LUA_DL_DLL) /* }{ */ +/* +** {====================================================================== +** This is an implementation of loadlib for Windows using native functions. +** ======================================================================= +*/ + +#include + + +/* +** optional flags for LoadLibraryEx +*/ +#if !defined(LUA_LLE_FLAGS) +#define LUA_LLE_FLAGS 0 +#endif + + +#undef setprogdir + + +/* +** Replace in the path (on the top of the stack) any occurrence +** of LUA_EXEC_DIR with the executable's path. +*/ +static void setprogdir (lua_State *L) { + char buff[MAX_PATH + 1]; + char *lb; + DWORD nsize = sizeof(buff)/sizeof(char); + DWORD n = GetModuleFileNameA(NULL, buff, nsize); /* get exec. name */ + if (n == 0 || n == nsize || (lb = strrchr(buff, '\\')) == NULL) + luaL_error(L, "unable to get ModuleFileName"); + else { + *lb = '\0'; /* cut name on the last '\\' to get the path */ + luaL_gsub(L, lua_tostring(L, -1), LUA_EXEC_DIR, buff); + lua_remove(L, -2); /* remove original string */ + } +} + + + + +static void pusherror (lua_State *L) { + int error = GetLastError(); + char buffer[128]; + if (FormatMessageA(FORMAT_MESSAGE_IGNORE_INSERTS | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, buffer, sizeof(buffer)/sizeof(char), NULL)) + lua_pushstring(L, buffer); + else + lua_pushfstring(L, "system error %d\n", error); +} + +static void lsys_unloadlib (void *lib) { + FreeLibrary((HMODULE)lib); +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + HMODULE lib = LoadLibraryExA(path, NULL, LUA_LLE_FLAGS); + (void)(seeglb); /* not used: symbols are 'global' by default */ + if (lib == NULL) pusherror(L); + return lib; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + lua_CFunction f = (lua_CFunction)GetProcAddress((HMODULE)lib, sym); + if (f == NULL) pusherror(L); + return f; +} + +/* }====================================================== */ + + +#else /* }{ */ +/* +** {====================================================== +** Fallback for other systems +** ======================================================= +*/ + +#undef LIB_FAIL +#define LIB_FAIL "absent" + + +#define DLMSG "dynamic libraries not enabled; check your Lua installation" + + +static void lsys_unloadlib (void *lib) { + (void)(lib); /* not used */ +} + + +static void *lsys_load (lua_State *L, const char *path, int seeglb) { + (void)(path); (void)(seeglb); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + + +static lua_CFunction lsys_sym (lua_State *L, void *lib, const char *sym) { + (void)(lib); (void)(sym); /* not used */ + lua_pushliteral(L, DLMSG); + return NULL; +} + +/* }====================================================== */ +#endif /* } */ + + +/* +** {================================================================== +** Set Paths +** =================================================================== +*/ + +/* +** LUA_PATH_VAR and LUA_CPATH_VAR are the names of the environment +** variables that Lua check to set its paths. +*/ +#if !defined(LUA_PATH_VAR) +#define LUA_PATH_VAR "LUA_PATH" +#endif + +#if !defined(LUA_CPATH_VAR) +#define LUA_CPATH_VAR "LUA_CPATH" +#endif + + +#define AUXMARK "\1" /* auxiliary mark */ + + +/* +** return registry.LUA_NOENV as a boolean +*/ +static int noenv (lua_State *L) { + int b; + lua_getfield(L, LUA_REGISTRYINDEX, "LUA_NOENV"); + b = lua_toboolean(L, -1); + lua_pop(L, 1); /* remove value */ + return b; +} + + +/* +** Set a path +*/ +static void setpath (lua_State *L, const char *fieldname, + const char *envname, + const char *dft) { + const char *nver = lua_pushfstring(L, "%s%s", envname, LUA_VERSUFFIX); + const char *path = getenv(nver); /* use versioned name */ + if (path == NULL) /* no environment variable? */ + path = getenv(envname); /* try unversioned name */ + if (path == NULL || noenv(L)) /* no environment variable? */ + lua_pushstring(L, dft); /* use default */ + else { + /* replace ";;" by ";AUXMARK;" and then AUXMARK by default path */ + path = luaL_gsub(L, path, LUA_PATH_SEP LUA_PATH_SEP, + LUA_PATH_SEP AUXMARK LUA_PATH_SEP); + luaL_gsub(L, path, AUXMARK, dft); + lua_remove(L, -2); /* remove result from 1st 'gsub' */ + } + setprogdir(L); + lua_setfield(L, -3, fieldname); /* package[fieldname] = path value */ + lua_pop(L, 1); /* pop versioned variable name */ +} + +/* }================================================================== */ + + +/* +** return registry.CLIBS[path] +*/ +static void *checkclib (lua_State *L, const char *path) { + void *plib; + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_getfield(L, -1, path); + plib = lua_touserdata(L, -1); /* plib = CLIBS[path] */ + lua_pop(L, 2); /* pop CLIBS table and 'plib' */ + return plib; +} + + +/* +** registry.CLIBS[path] = plib -- for queries +** registry.CLIBS[#CLIBS + 1] = plib -- also keep a list of all libraries +*/ +static void addtoclib (lua_State *L, const char *path, void *plib) { + lua_rawgetp(L, LUA_REGISTRYINDEX, &CLIBS); + lua_pushlightuserdata(L, plib); + lua_pushvalue(L, -1); + lua_setfield(L, -3, path); /* CLIBS[path] = plib */ + lua_rawseti(L, -2, luaL_len(L, -2) + 1); /* CLIBS[#CLIBS + 1] = plib */ + lua_pop(L, 1); /* pop CLIBS table */ +} + + +/* +** __gc tag method for CLIBS table: calls 'lsys_unloadlib' for all lib +** handles in list CLIBS +*/ +static int gctm (lua_State *L) { + lua_Integer n = luaL_len(L, 1); + for (; n >= 1; n--) { /* for each handle, in reverse order */ + lua_rawgeti(L, 1, n); /* get handle CLIBS[n] */ + lsys_unloadlib(lua_touserdata(L, -1)); + lua_pop(L, 1); /* pop handle */ + } + return 0; +} + + + +/* error codes for 'lookforfunc' */ +#define ERRLIB 1 +#define ERRFUNC 2 + +/* +** Look for a C function named 'sym' in a dynamically loaded library +** 'path'. +** First, check whether the library is already loaded; if not, try +** to load it. +** Then, if 'sym' is '*', return true (as library has been loaded). +** Otherwise, look for symbol 'sym' in the library and push a +** C function with that symbol. +** Return 0 and 'true' or a function in the stack; in case of +** errors, return an error code and an error message in the stack. +*/ +static int lookforfunc (lua_State *L, const char *path, const char *sym) { + void *reg = checkclib(L, path); /* check loaded C libraries */ + if (reg == NULL) { /* must load library? */ + reg = lsys_load(L, path, *sym == '*'); /* global symbols if 'sym'=='*' */ + if (reg == NULL) return ERRLIB; /* unable to load library */ + addtoclib(L, path, reg); + } + if (*sym == '*') { /* loading only library (no function)? */ + lua_pushboolean(L, 1); /* return 'true' */ + return 0; /* no errors */ + } + else { + lua_CFunction f = lsys_sym(L, reg, sym); + if (f == NULL) + return ERRFUNC; /* unable to find function */ + lua_pushcfunction(L, f); /* else create new function */ + return 0; /* no errors */ + } +} + + +static int ll_loadlib (lua_State *L) { + const char *path = luaL_checkstring(L, 1); + const char *init = luaL_checkstring(L, 2); + int stat = lookforfunc(L, path, init); + if (stat == 0) /* no errors? */ + return 1; /* return the loaded function */ + else { /* error; error message is on stack top */ + lua_pushnil(L); + lua_insert(L, -2); + lua_pushstring(L, (stat == ERRLIB) ? LIB_FAIL : "init"); + return 3; /* return nil, error message, and where */ + } +} + + + +/* +** {====================================================== +** 'require' function +** ======================================================= +*/ + + +static int readable (const char *filename) { + FILE *f = fopen(filename, "r"); /* try to open file */ + if (f == NULL) return 0; /* open failed */ + fclose(f); + return 1; +} + + +static const char *pushnexttemplate (lua_State *L, const char *path) { + const char *l; + while (*path == *LUA_PATH_SEP) path++; /* skip separators */ + if (*path == '\0') return NULL; /* no more templates */ + l = strchr(path, *LUA_PATH_SEP); /* find next separator */ + if (l == NULL) l = path + strlen(path); + lua_pushlstring(L, path, l - path); /* template */ + return l; +} + + +static const char *searchpath (lua_State *L, const char *name, + const char *path, + const char *sep, + const char *dirsep) { + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + if (*sep != '\0') /* non-empty separator? */ + name = luaL_gsub(L, name, sep, dirsep); /* replace it by 'dirsep' */ + while ((path = pushnexttemplate(L, path)) != NULL) { + const char *filename = luaL_gsub(L, lua_tostring(L, -1), + LUA_PATH_MARK, name); + lua_remove(L, -2); /* remove path template */ + if (readable(filename)) /* does file exist and is readable? */ + return filename; /* return that file name */ + lua_pushfstring(L, "\n\tno file '%s'", filename); + lua_remove(L, -2); /* remove file name */ + luaL_addvalue(&msg); /* concatenate error msg. entry */ + } + luaL_pushresult(&msg); /* create error message */ + return NULL; /* not found */ +} + + +static int ll_searchpath (lua_State *L) { + const char *f = searchpath(L, luaL_checkstring(L, 1), + luaL_checkstring(L, 2), + luaL_optstring(L, 3, "."), + luaL_optstring(L, 4, LUA_DIRSEP)); + if (f != NULL) return 1; + else { /* error message is on top of the stack */ + lua_pushnil(L); + lua_insert(L, -2); + return 2; /* return nil + error message */ + } +} + + +static const char *findfile (lua_State *L, const char *name, + const char *pname, + const char *dirsep) { + const char *path; + lua_getfield(L, lua_upvalueindex(1), pname); + path = lua_tostring(L, -1); + if (path == NULL) + luaL_error(L, "'package.%s' must be a string", pname); + return searchpath(L, name, path, ".", dirsep); +} + + +static int checkload (lua_State *L, int stat, const char *filename) { + if (stat) { /* module loaded successfully? */ + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; /* return open function and file name */ + } + else + return luaL_error(L, "error loading module '%s' from file '%s':\n\t%s", + lua_tostring(L, 1), filename, lua_tostring(L, -1)); +} + + +static int searcher_Lua (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + filename = findfile(L, name, "path", LUA_LSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (luaL_loadfile(L, filename) == LUA_OK), filename); +} + + +/* +** Try to find a load function for module 'modname' at file 'filename'. +** First, change '.' to '_' in 'modname'; then, if 'modname' has +** the form X-Y (that is, it has an "ignore mark"), build a function +** name "luaopen_X" and look for it. (For compatibility, if that +** fails, it also tries "luaopen_Y".) If there is no ignore mark, +** look for a function named "luaopen_modname". +*/ +static int loadfunc (lua_State *L, const char *filename, const char *modname) { + const char *openfunc; + const char *mark; + modname = luaL_gsub(L, modname, ".", LUA_OFSEP); + mark = strchr(modname, *LUA_IGMARK); + if (mark) { + int stat; + openfunc = lua_pushlstring(L, modname, mark - modname); + openfunc = lua_pushfstring(L, LUA_POF"%s", openfunc); + stat = lookforfunc(L, filename, openfunc); + if (stat != ERRFUNC) return stat; + modname = mark + 1; /* else go ahead and try old-style name */ + } + openfunc = lua_pushfstring(L, LUA_POF"%s", modname); + return lookforfunc(L, filename, openfunc); +} + + +static int searcher_C (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + const char *filename = findfile(L, name, "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* module not found in this path */ + return checkload(L, (loadfunc(L, filename, name) == 0), filename); +} + + +static int searcher_Croot (lua_State *L) { + const char *filename; + const char *name = luaL_checkstring(L, 1); + const char *p = strchr(name, '.'); + int stat; + if (p == NULL) return 0; /* is root */ + lua_pushlstring(L, name, p - name); + filename = findfile(L, lua_tostring(L, -1), "cpath", LUA_CSUBSEP); + if (filename == NULL) return 1; /* root not found */ + if ((stat = loadfunc(L, filename, name)) != 0) { + if (stat != ERRFUNC) + return checkload(L, 0, filename); /* real error */ + else { /* open function not found */ + lua_pushfstring(L, "\n\tno module '%s' in file '%s'", name, filename); + return 1; + } + } + lua_pushstring(L, filename); /* will be 2nd argument to module */ + return 2; +} + + +static int searcher_preload (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_getfield(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + if (lua_getfield(L, -1, name) == LUA_TNIL) /* not found? */ + lua_pushfstring(L, "\n\tno field package.preload['%s']", name); + return 1; +} + + +static void findloader (lua_State *L, const char *name) { + int i; + luaL_Buffer msg; /* to build error message */ + luaL_buffinit(L, &msg); + /* push 'package.searchers' to index 3 in the stack */ + if (lua_getfield(L, lua_upvalueindex(1), "searchers") != LUA_TTABLE) + luaL_error(L, "'package.searchers' must be a table"); + /* iterate over available searchers to find a loader */ + for (i = 1; ; i++) { + if (lua_rawgeti(L, 3, i) == LUA_TNIL) { /* no more searchers? */ + lua_pop(L, 1); /* remove nil */ + luaL_pushresult(&msg); /* create error message */ + luaL_error(L, "module '%s' not found:%s", name, lua_tostring(L, -1)); + } + lua_pushstring(L, name); + lua_call(L, 1, 2); /* call it */ + if (lua_isfunction(L, -2)) /* did it find a loader? */ + return; /* module loader found */ + else if (lua_isstring(L, -2)) { /* searcher returned error message? */ + lua_pop(L, 1); /* remove extra return */ + luaL_addvalue(&msg); /* concatenate error message */ + } + else + lua_pop(L, 2); /* remove both returns */ + } +} + + +static int ll_require (lua_State *L) { + const char *name = luaL_checkstring(L, 1); + lua_settop(L, 1); /* LOADED table will be at index 2 */ + lua_getfield(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_getfield(L, 2, name); /* LOADED[name] */ + if (lua_toboolean(L, -1)) /* is it there? */ + return 1; /* package is already loaded */ + /* else must load package */ + lua_pop(L, 1); /* remove 'getfield' result */ + findloader(L, name); + lua_pushstring(L, name); /* pass name as argument to module loader */ + lua_insert(L, -2); /* name is 1st argument (before search data) */ + lua_call(L, 2, 1); /* run loader to load module */ + if (!lua_isnil(L, -1)) /* non-nil return? */ + lua_setfield(L, 2, name); /* LOADED[name] = returned value */ + if (lua_getfield(L, 2, name) == LUA_TNIL) { /* module set no value? */ + lua_pushboolean(L, 1); /* use true as result */ + lua_pushvalue(L, -1); /* extra copy to be returned */ + lua_setfield(L, 2, name); /* LOADED[name] = true */ + } + return 1; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** 'module' function +** ======================================================= +*/ +#if defined(LUA_COMPAT_MODULE) + +/* +** changes the environment variable of calling function +*/ +static void set_env (lua_State *L) { + lua_Debug ar; + if (lua_getstack(L, 1, &ar) == 0 || + lua_getinfo(L, "f", &ar) == 0 || /* get calling function */ + lua_iscfunction(L, -1)) + luaL_error(L, "'module' not called from a Lua function"); + lua_pushvalue(L, -2); /* copy new environment table to top */ + lua_setupvalue(L, -2, 1); + lua_pop(L, 1); /* remove function */ +} + + +static void dooptions (lua_State *L, int n) { + int i; + for (i = 2; i <= n; i++) { + if (lua_isfunction(L, i)) { /* avoid 'calling' extra info. */ + lua_pushvalue(L, i); /* get option (a function) */ + lua_pushvalue(L, -2); /* module */ + lua_call(L, 1, 0); + } + } +} + + +static void modinit (lua_State *L, const char *modname) { + const char *dot; + lua_pushvalue(L, -1); + lua_setfield(L, -2, "_M"); /* module._M = module */ + lua_pushstring(L, modname); + lua_setfield(L, -2, "_NAME"); + dot = strrchr(modname, '.'); /* look for last dot in module name */ + if (dot == NULL) dot = modname; + else dot++; + /* set _PACKAGE as package name (full module name minus last part) */ + lua_pushlstring(L, modname, dot - modname); + lua_setfield(L, -2, "_PACKAGE"); +} + + +static int ll_module (lua_State *L) { + const char *modname = luaL_checkstring(L, 1); + int lastarg = lua_gettop(L); /* last parameter */ + luaL_pushmodule(L, modname, 1); /* get/create module table */ + /* check whether table already has a _NAME field */ + if (lua_getfield(L, -1, "_NAME") != LUA_TNIL) + lua_pop(L, 1); /* table is an initialized module */ + else { /* no; initialize it */ + lua_pop(L, 1); + modinit(L, modname); + } + lua_pushvalue(L, -1); + set_env(L); + dooptions(L, lastarg); + return 1; +} + + +static int ll_seeall (lua_State *L) { + luaL_checktype(L, 1, LUA_TTABLE); + if (!lua_getmetatable(L, 1)) { + lua_createtable(L, 0, 1); /* create new metatable */ + lua_pushvalue(L, -1); + lua_setmetatable(L, 1); + } + lua_pushglobaltable(L); + lua_setfield(L, -2, "__index"); /* mt.__index = _G */ + return 0; +} + +#endif +/* }====================================================== */ + + + +static const luaL_Reg pk_funcs[] = { + {"loadlib", ll_loadlib}, + {"searchpath", ll_searchpath}, +#if defined(LUA_COMPAT_MODULE) + {"seeall", ll_seeall}, +#endif + /* placeholders */ + {"preload", NULL}, + {"cpath", NULL}, + {"path", NULL}, + {"searchers", NULL}, + {"loaded", NULL}, + {NULL, NULL} +}; + + +static const luaL_Reg ll_funcs[] = { +#if defined(LUA_COMPAT_MODULE) + {"module", ll_module}, +#endif + {"require", ll_require}, + {NULL, NULL} +}; + + +static void createsearcherstable (lua_State *L) { + static const lua_CFunction searchers[] = + {searcher_preload, searcher_Lua, searcher_C, searcher_Croot, NULL}; + int i; + /* create 'searchers' table */ + lua_createtable(L, sizeof(searchers)/sizeof(searchers[0]) - 1, 0); + /* fill it with predefined searchers */ + for (i=0; searchers[i] != NULL; i++) { + lua_pushvalue(L, -2); /* set 'package' as upvalue for all searchers */ + lua_pushcclosure(L, searchers[i], 1); + lua_rawseti(L, -2, i+1); + } +#if defined(LUA_COMPAT_LOADERS) + lua_pushvalue(L, -1); /* make a copy of 'searchers' table */ + lua_setfield(L, -3, "loaders"); /* put it in field 'loaders' */ +#endif + lua_setfield(L, -2, "searchers"); /* put it in field 'searchers' */ +} + + +/* +** create table CLIBS to keep track of loaded C libraries, +** setting a finalizer to close all libraries when closing state. +*/ +static void createclibstable (lua_State *L) { + lua_newtable(L); /* create CLIBS table */ + lua_createtable(L, 0, 1); /* create metatable for CLIBS */ + lua_pushcfunction(L, gctm); + lua_setfield(L, -2, "__gc"); /* set finalizer for CLIBS table */ + lua_setmetatable(L, -2); + lua_rawsetp(L, LUA_REGISTRYINDEX, &CLIBS); /* set CLIBS table in registry */ +} + + +LUAMOD_API int luaopen_package (lua_State *L) { + createclibstable(L); + luaL_newlib(L, pk_funcs); /* create 'package' table */ + createsearcherstable(L); + /* set paths */ + setpath(L, "path", LUA_PATH_VAR, LUA_PATH_DEFAULT); + setpath(L, "cpath", LUA_CPATH_VAR, LUA_CPATH_DEFAULT); + /* store config information */ + lua_pushliteral(L, LUA_DIRSEP "\n" LUA_PATH_SEP "\n" LUA_PATH_MARK "\n" + LUA_EXEC_DIR "\n" LUA_IGMARK "\n"); + lua_setfield(L, -2, "config"); + /* set field 'loaded' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_LOADED_TABLE); + lua_setfield(L, -2, "loaded"); + /* set field 'preload' */ + luaL_getsubtable(L, LUA_REGISTRYINDEX, LUA_PRELOAD_TABLE); + lua_setfield(L, -2, "preload"); + lua_pushglobaltable(L); + lua_pushvalue(L, -2); /* set 'package' as upvalue for next lib */ + luaL_setfuncs(L, ll_funcs, 1); /* open lib into global table */ + lua_pop(L, 1); /* pop global table */ + return 1; /* return 'package' table */ +} + diff --git a/src/lua/lobject.c b/src/lua/lobject.c new file mode 100644 index 000000000000..355bf58d6372 --- /dev/null +++ b/src/lua/lobject.c @@ -0,0 +1,522 @@ +/* +** $Id: lobject.c,v 2.113.1.1 2017/04/19 17:29:57 roberto Exp $ +** Some generic functions over Lua objects +** See Copyright Notice in lua.h +*/ + +#define lobject_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lctype.h" +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "lvm.h" + + + +LUAI_DDEF const TValue luaO_nilobject_ = {NILCONSTANT}; + + +/* +** converts an integer to a "floating point byte", represented as +** (eeeeexxx), where the real value is (1xxx) * 2^(eeeee - 1) if +** eeeee != 0 and (xxx) otherwise. +*/ +int luaO_int2fb (unsigned int x) { + int e = 0; /* exponent */ + if (x < 8) return x; + while (x >= (8 << 4)) { /* coarse steps */ + x = (x + 0xf) >> 4; /* x = ceil(x / 16) */ + e += 4; + } + while (x >= (8 << 1)) { /* fine steps */ + x = (x + 1) >> 1; /* x = ceil(x / 2) */ + e++; + } + return ((e+1) << 3) | (cast_int(x) - 8); +} + + +/* converts back */ +int luaO_fb2int (int x) { + return (x < 8) ? x : ((x & 7) + 8) << ((x >> 3) - 1); +} + + +/* +** Computes ceil(log2(x)) +*/ +int luaO_ceillog2 (unsigned int x) { + static const lu_byte log_2[256] = { /* log_2[i] = ceil(log2(i - 1)) */ + 0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5, + 6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8, + 8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8 + }; + int l = 0; + x--; + while (x >= 256) { l += 8; x >>= 8; } + return l + log_2[x]; +} + + +static lua_Integer intarith (lua_State *L, int op, lua_Integer v1, + lua_Integer v2) { + switch (op) { + case LUA_OPADD: return intop(+, v1, v2); + case LUA_OPSUB:return intop(-, v1, v2); + case LUA_OPMUL:return intop(*, v1, v2); + case LUA_OPMOD: return luaV_mod(L, v1, v2); + case LUA_OPIDIV: return luaV_div(L, v1, v2); + case LUA_OPBAND: return intop(&, v1, v2); + case LUA_OPBOR: return intop(|, v1, v2); + case LUA_OPBXOR: return intop(^, v1, v2); + case LUA_OPSHL: return luaV_shiftl(v1, v2); + case LUA_OPSHR: return luaV_shiftl(v1, -v2); + case LUA_OPUNM: return intop(-, 0, v1); + case LUA_OPBNOT: return intop(^, ~l_castS2U(0), v1); + default: lua_assert(0); return 0; + } +} + + +static lua_Number numarith (lua_State *L, int op, lua_Number v1, + lua_Number v2) { + switch (op) { + case LUA_OPADD: return luai_numadd(L, v1, v2); + case LUA_OPSUB: return luai_numsub(L, v1, v2); + case LUA_OPMUL: return luai_nummul(L, v1, v2); + case LUA_OPDIV: return luai_numdiv(L, v1, v2); + case LUA_OPPOW: return luai_numpow(L, v1, v2); + case LUA_OPIDIV: return luai_numidiv(L, v1, v2); + case LUA_OPUNM: return luai_numunm(L, v1); + case LUA_OPMOD: { + lua_Number m; + luai_nummod(L, v1, v2, m); + return m; + } + default: lua_assert(0); return 0; + } +} + + +void luaO_arith (lua_State *L, int op, const TValue *p1, const TValue *p2, + TValue *res) { + switch (op) { + case LUA_OPBAND: case LUA_OPBOR: case LUA_OPBXOR: + case LUA_OPSHL: case LUA_OPSHR: + case LUA_OPBNOT: { /* operate only on integers */ + lua_Integer i1; lua_Integer i2; + if (tointeger(p1, &i1) && tointeger(p2, &i2)) { + setivalue(res, intarith(L, op, i1, i2)); + return; + } + else break; /* go to the end */ + } + case LUA_OPDIV: case LUA_OPPOW: { /* operate only on floats */ + lua_Number n1; lua_Number n2; + if (tonumber(p1, &n1) && tonumber(p2, &n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return; + } + else break; /* go to the end */ + } + default: { /* other operations */ + lua_Number n1; lua_Number n2; + if (ttisinteger(p1) && ttisinteger(p2)) { + setivalue(res, intarith(L, op, ivalue(p1), ivalue(p2))); + return; + } + else if (tonumber(p1, &n1) && tonumber(p2, &n2)) { + setfltvalue(res, numarith(L, op, n1, n2)); + return; + } + else break; /* go to the end */ + } + } + /* could not perform raw operation; try metamethod */ + lua_assert(L != NULL); /* should not fail when folding (compile time) */ + luaT_trybinTM(L, p1, p2, res, cast(TMS, (op - LUA_OPADD) + TM_ADD)); +} + + +int luaO_hexavalue (int c) { + if (lisdigit(c)) return c - '0'; + else return (ltolower(c) - 'a') + 10; +} + + +static int isneg (const char **s) { + if (**s == '-') { (*s)++; return 1; } + else if (**s == '+') (*s)++; + return 0; +} + + + +/* +** {================================================================== +** Lua's implementation for 'lua_strx2number' +** =================================================================== +*/ + +#if !defined(lua_strx2number) + +/* maximum number of significant digits to read (to avoid overflows + even with single floats) */ +#define MAXSIGDIG 30 + +/* +** convert an hexadecimal numeric string to a number, following +** C99 specification for 'strtod' +*/ +static lua_Number lua_strx2number (const char *s, char **endptr) { + int dot = lua_getlocaledecpoint(); + lua_Number r = 0.0; /* result (accumulator) */ + int sigdig = 0; /* number of significant digits */ + int nosigdig = 0; /* number of non-significant digits */ + int e = 0; /* exponent correction */ + int neg; /* 1 if number is negative */ + int hasdot = 0; /* true after seen a dot */ + *endptr = cast(char *, s); /* nothing is valid yet */ + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); /* check signal */ + if (!(*s == '0' && (*(s + 1) == 'x' || *(s + 1) == 'X'))) /* check '0x' */ + return 0.0; /* invalid format (no '0x') */ + for (s += 2; ; s++) { /* skip '0x' and read numeral */ + if (*s == dot) { + if (hasdot) break; /* second dot? stop loop */ + else hasdot = 1; + } + else if (lisxdigit(cast_uchar(*s))) { + if (sigdig == 0 && *s == '0') /* non-significant digit (zero)? */ + nosigdig++; + else if (++sigdig <= MAXSIGDIG) /* can read it without overflow? */ + r = (r * cast_num(16.0)) + luaO_hexavalue(*s); + else e++; /* too many digits; ignore, but still count for exponent */ + if (hasdot) e--; /* decimal digit? correct exponent */ + } + else break; /* neither a dot nor a digit */ + } + if (nosigdig + sigdig == 0) /* no digits? */ + return 0.0; /* invalid format */ + *endptr = cast(char *, s); /* valid up to here */ + e *= 4; /* each digit multiplies/divides value by 2^4 */ + if (*s == 'p' || *s == 'P') { /* exponent part? */ + int exp1 = 0; /* exponent value */ + int neg1; /* exponent signal */ + s++; /* skip 'p' */ + neg1 = isneg(&s); /* signal */ + if (!lisdigit(cast_uchar(*s))) + return 0.0; /* invalid; must have at least one digit */ + while (lisdigit(cast_uchar(*s))) /* read exponent */ + exp1 = exp1 * 10 + *(s++) - '0'; + if (neg1) exp1 = -exp1; + e += exp1; + *endptr = cast(char *, s); /* valid up to here */ + } + if (neg) r = -r; + return l_mathop(ldexp)(r, e); +} + +#endif +/* }====================================================== */ + + +/* maximum length of a numeral */ +#if !defined (L_MAXLENNUM) +#define L_MAXLENNUM 200 +#endif + +static const char *l_str2dloc (const char *s, lua_Number *result, int mode) { + char *endptr; + *result = (mode == 'x') ? lua_strx2number(s, &endptr) /* try to convert */ + : lua_str2number(s, &endptr); + if (endptr == s) return NULL; /* nothing recognized? */ + while (lisspace(cast_uchar(*endptr))) endptr++; /* skip trailing spaces */ + return (*endptr == '\0') ? endptr : NULL; /* OK if no trailing characters */ +} + + +/* +** Convert string 's' to a Lua number (put in 'result'). Return NULL +** on fail or the address of the ending '\0' on success. +** 'pmode' points to (and 'mode' contains) special things in the string: +** - 'x'/'X' means an hexadecimal numeral +** - 'n'/'N' means 'inf' or 'nan' (which should be rejected) +** - '.' just optimizes the search for the common case (nothing special) +** This function accepts both the current locale or a dot as the radix +** mark. If the conversion fails, it may mean number has a dot but +** locale accepts something else. In that case, the code copies 's' +** to a buffer (because 's' is read-only), changes the dot to the +** current locale radix mark, and tries to convert again. +*/ +static const char *l_str2d (const char *s, lua_Number *result) { + const char *endptr; + const char *pmode = strpbrk(s, ".xXnN"); + int mode = pmode ? ltolower(cast_uchar(*pmode)) : 0; + if (mode == 'n') /* reject 'inf' and 'nan' */ + return NULL; + endptr = l_str2dloc(s, result, mode); /* try to convert */ + if (endptr == NULL) { /* failed? may be a different locale */ + char buff[L_MAXLENNUM + 1]; + const char *pdot = strchr(s, '.'); + if (strlen(s) > L_MAXLENNUM || pdot == NULL) + return NULL; /* string too long or no dot; fail */ + strcpy(buff, s); /* copy string to buffer */ + buff[pdot - s] = lua_getlocaledecpoint(); /* correct decimal point */ + endptr = l_str2dloc(buff, result, mode); /* try again */ + if (endptr != NULL) + endptr = s + (endptr - buff); /* make relative to 's' */ + } + return endptr; +} + + +#define MAXBY10 cast(lua_Unsigned, LUA_MAXINTEGER / 10) +#define MAXLASTD cast_int(LUA_MAXINTEGER % 10) + +static const char *l_str2int (const char *s, lua_Integer *result) { + lua_Unsigned a = 0; + int empty = 1; + int neg; + while (lisspace(cast_uchar(*s))) s++; /* skip initial spaces */ + neg = isneg(&s); + if (s[0] == '0' && + (s[1] == 'x' || s[1] == 'X')) { /* hex? */ + s += 2; /* skip '0x' */ + for (; lisxdigit(cast_uchar(*s)); s++) { + a = a * 16 + luaO_hexavalue(*s); + empty = 0; + } + } + else { /* decimal */ + for (; lisdigit(cast_uchar(*s)); s++) { + int d = *s - '0'; + if (a >= MAXBY10 && (a > MAXBY10 || d > MAXLASTD + neg)) /* overflow? */ + return NULL; /* do not accept it (as integer) */ + a = a * 10 + d; + empty = 0; + } + } + while (lisspace(cast_uchar(*s))) s++; /* skip trailing spaces */ + if (empty || *s != '\0') return NULL; /* something wrong in the numeral */ + else { + *result = l_castU2S((neg) ? 0u - a : a); + return s; + } +} + + +size_t luaO_str2num (const char *s, TValue *o) { + lua_Integer i; lua_Number n; + const char *e; + if ((e = l_str2int(s, &i)) != NULL) { /* try as an integer */ + setivalue(o, i); + } + else if ((e = l_str2d(s, &n)) != NULL) { /* else try as a float */ + setfltvalue(o, n); + } + else + return 0; /* conversion failed */ + return (e - s) + 1; /* success; return string size */ +} + + +int luaO_utf8esc (char *buff, unsigned long x) { + int n = 1; /* number of bytes put in buffer (backwards) */ + lua_assert(x <= 0x10FFFF); + if (x < 0x80) /* ascii? */ + buff[UTF8BUFFSZ - 1] = cast(char, x); + else { /* need continuation bytes */ + unsigned int mfb = 0x3f; /* maximum that fits in first byte */ + do { /* add continuation bytes */ + buff[UTF8BUFFSZ - (n++)] = cast(char, 0x80 | (x & 0x3f)); + x >>= 6; /* remove added bits */ + mfb >>= 1; /* now there is one less bit available in first byte */ + } while (x > mfb); /* still needs continuation byte? */ + buff[UTF8BUFFSZ - n] = cast(char, (~mfb << 1) | x); /* add first byte */ + } + return n; +} + + +/* maximum length of the conversion of a number to a string */ +#define MAXNUMBER2STR 50 + + +/* +** Convert a number object to a string +*/ +void luaO_tostring (lua_State *L, StkId obj) { + char buff[MAXNUMBER2STR]; + size_t len; + lua_assert(ttisnumber(obj)); + if (ttisinteger(obj)) + len = lua_integer2str(buff, sizeof(buff), ivalue(obj)); + else { + len = lua_number2str(buff, sizeof(buff), fltvalue(obj)); +#if !defined(LUA_COMPAT_FLOATSTRING) + if (buff[strspn(buff, "-0123456789")] == '\0') { /* looks like an int? */ + buff[len++] = lua_getlocaledecpoint(); + buff[len++] = '0'; /* adds '.0' to result */ + } +#endif + } + setsvalue2s(L, obj, luaS_newlstr(L, buff, len)); +} + + +static void pushstr (lua_State *L, const char *str, size_t l) { + setsvalue2s(L, L->top, luaS_newlstr(L, str, l)); + luaD_inctop(L); +} + + +/* +** this function handles only '%d', '%c', '%f', '%p', and '%s' + conventional formats, plus Lua-specific '%I' and '%U' +*/ +const char *luaO_pushvfstring (lua_State *L, const char *fmt, va_list argp) { + int n = 0; + for (;;) { + const char *e = strchr(fmt, '%'); + if (e == NULL) break; + pushstr(L, fmt, e - fmt); + switch (*(e+1)) { + case 's': { /* zero-terminated string */ + const char *s = va_arg(argp, char *); + if (s == NULL) s = "(null)"; + pushstr(L, s, strlen(s)); + break; + } + case 'c': { /* an 'int' as a character */ + char buff = cast(char, va_arg(argp, int)); + if (lisprint(cast_uchar(buff))) + pushstr(L, &buff, 1); + else /* non-printable character; print its code */ + luaO_pushfstring(L, "<\\%d>", cast_uchar(buff)); + break; + } + case 'd': { /* an 'int' */ + setivalue(L->top, va_arg(argp, int)); + goto top2str; + } + case 'I': { /* a 'lua_Integer' */ + setivalue(L->top, cast(lua_Integer, va_arg(argp, l_uacInt))); + goto top2str; + } + case 'f': { /* a 'lua_Number' */ + setfltvalue(L->top, cast_num(va_arg(argp, l_uacNumber))); + top2str: /* convert the top element to a string */ + luaD_inctop(L); + luaO_tostring(L, L->top - 1); + break; + } + case 'p': { /* a pointer */ + char buff[4*sizeof(void *) + 8]; /* should be enough space for a '%p' */ + void *p = va_arg(argp, void *); + int l = lua_pointer2str(buff, sizeof(buff), p); + pushstr(L, buff, l); + break; + } + case 'U': { /* an 'int' as a UTF-8 sequence */ + char buff[UTF8BUFFSZ]; + int l = luaO_utf8esc(buff, cast(long, va_arg(argp, long))); + pushstr(L, buff + UTF8BUFFSZ - l, l); + break; + } + case '%': { + pushstr(L, "%", 1); + break; + } + default: { + luaG_runerror(L, "invalid option '%%%c' to 'lua_pushfstring'", + *(e + 1)); + } + } + n += 2; + fmt = e+2; + } + luaD_checkstack(L, 1); + pushstr(L, fmt, strlen(fmt)); + if (n > 0) luaV_concat(L, n + 1); + return svalue(L->top - 1); +} + + +const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { + const char *msg; + va_list argp; + va_start(argp, fmt); + msg = luaO_pushvfstring(L, fmt, argp); + va_end(argp); + return msg; +} + + +/* number of chars of a literal string without the ending \0 */ +#define LL(x) (sizeof(x)/sizeof(char) - 1) + +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" + +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) + +void luaO_chunkid (char *out, const char *source, size_t bufflen) { + size_t l = strlen(source); + if (*source == '=') { /* 'literal' source */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* truncate it */ + addstr(out, source + 1, bufflen - 1); + *out = '\0'; + } + } + else if (*source == '@') { /* file name */ + if (l <= bufflen) /* small enough? */ + memcpy(out, source + 1, l * sizeof(char)); + else { /* add '...' before rest of name */ + addstr(out, RETS, LL(RETS)); + bufflen -= LL(RETS); + memcpy(out, source + 1 + l - bufflen, bufflen * sizeof(char)); + } + } + else { /* string; format as [string "source"] */ + const char *nl = strchr(source, '\n'); /* find first new line (if any) */ + addstr(out, PRE, LL(PRE)); /* add prefix */ + bufflen -= LL(PRE RETS POS) + 1; /* save space for prefix+suffix+'\0' */ + if (l < bufflen && nl == NULL) { /* small one-line source? */ + addstr(out, source, l); /* keep it */ + } + else { + if (nl != NULL) l = nl - source; /* stop at first newline */ + if (l > bufflen) l = bufflen; + addstr(out, source, l); + addstr(out, RETS, LL(RETS)); + } + memcpy(out, POS, (LL(POS) + 1) * sizeof(char)); + } +} + diff --git a/src/lua/lobject.h b/src/lua/lobject.h new file mode 100644 index 000000000000..24088614027f --- /dev/null +++ b/src/lua/lobject.h @@ -0,0 +1,549 @@ +/* +** $Id: lobject.h,v 2.117.1.1 2017/04/19 17:39:34 roberto Exp $ +** Type definitions for Lua objects +** See Copyright Notice in lua.h +*/ + + +#ifndef lobject_h +#define lobject_h + + +#include + + +#include "llimits.h" +#include "lua.h" + + +/* +** Extra tags for non-values +*/ +#define LUA_TPROTO LUA_NUMTAGS /* function prototypes */ +#define LUA_TDEADKEY (LUA_NUMTAGS+1) /* removed keys in tables */ + +/* +** number of all possible tags (including LUA_TNONE but excluding DEADKEY) +*/ +#define LUA_TOTALTAGS (LUA_TPROTO + 2) + + +/* +** tags for Tagged Values have the following use of bits: +** bits 0-3: actual tag (a LUA_T* value) +** bits 4-5: variant bits +** bit 6: whether value is collectable +*/ + + +/* +** LUA_TFUNCTION variants: +** 0 - Lua function +** 1 - light C function +** 2 - regular C function (closure) +*/ + +/* Variant tags for functions */ +#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ +#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ +#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ + + +/* Variant tags for strings */ +#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ +#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ + + +/* Variant tags for numbers */ +#define LUA_TNUMFLT (LUA_TNUMBER | (0 << 4)) /* float numbers */ +#define LUA_TNUMINT (LUA_TNUMBER | (1 << 4)) /* integer numbers */ + + +/* Bit mark for collectable types */ +#define BIT_ISCOLLECTABLE (1 << 6) + +/* mark a tag as collectable */ +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) + + +/* +** Common type for all collectable objects +*/ +typedef struct GCObject GCObject; + + +/* +** Common Header for all collectable objects (in macro form, to be +** included in other objects) +*/ +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked + + +/* +** Common type has only the common header +*/ +struct GCObject { + CommonHeader; +}; + + + + +/* +** Tagged Values. This is the basic representation of values in Lua, +** an actual value plus a tag with its type. +*/ + +/* +** Union of all Lua values +*/ +typedef union Value { + GCObject *gc; /* collectable objects */ + void *p; /* light userdata */ + int b; /* booleans */ + lua_CFunction f; /* light C functions */ + lua_Integer i; /* integer numbers */ + lua_Number n; /* float numbers */ +} Value; + + +#define TValuefields Value value_; int tt_ + + +typedef struct lua_TValue { + TValuefields; +} TValue; + + + +/* macro defining a nil value */ +#define NILCONSTANT {NULL}, LUA_TNIL + + +#define val_(o) ((o)->value_) + + +/* raw type tag of a TValue */ +#define rttype(o) ((o)->tt_) + +/* tag with no variants (bits 0-3) */ +#define novariant(x) ((x) & 0x0F) + +/* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ +#define ttype(o) (rttype(o) & 0x3F) + +/* type tag of a TValue with no variants (bits 0-3) */ +#define ttnov(o) (novariant(rttype(o))) + + +/* Macros to test type */ +#define checktag(o,t) (rttype(o) == (t)) +#define checktype(o,t) (ttnov(o) == (t)) +#define ttisnumber(o) checktype((o), LUA_TNUMBER) +#define ttisfloat(o) checktag((o), LUA_TNUMFLT) +#define ttisinteger(o) checktag((o), LUA_TNUMINT) +#define ttisnil(o) checktag((o), LUA_TNIL) +#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) +#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisstring(o) checktype((o), LUA_TSTRING) +#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) +#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) +#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) +#define ttisfunction(o) checktype(o, LUA_TFUNCTION) +#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) +#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) +#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) +#define ttislcf(o) checktag((o), LUA_TLCF) +#define ttisfulluserdata(o) checktag((o), ctb(LUA_TUSERDATA)) +#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) +#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) + + +/* Macros to access values */ +#define ivalue(o) check_exp(ttisinteger(o), val_(o).i) +#define fltvalue(o) check_exp(ttisfloat(o), val_(o).n) +#define nvalue(o) check_exp(ttisnumber(o), \ + (ttisinteger(o) ? cast_num(ivalue(o)) : fltvalue(o))) +#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) +#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define tsvalue(o) check_exp(ttisstring(o), gco2ts(val_(o).gc)) +#define uvalue(o) check_exp(ttisfulluserdata(o), gco2u(val_(o).gc)) +#define clvalue(o) check_exp(ttisclosure(o), gco2cl(val_(o).gc)) +#define clLvalue(o) check_exp(ttisLclosure(o), gco2lcl(val_(o).gc)) +#define clCvalue(o) check_exp(ttisCclosure(o), gco2ccl(val_(o).gc)) +#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define hvalue(o) check_exp(ttistable(o), gco2t(val_(o).gc)) +#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) +#define thvalue(o) check_exp(ttisthread(o), gco2th(val_(o).gc)) +/* a dead value may get the 'gc' field, but cannot access its contents */ +#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) + +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) + + +#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) + + +/* Macros for internal tests */ +#define righttt(obj) (ttype(obj) == gcvalue(obj)->tt) + +#define checkliveness(L,obj) \ + lua_longassert(!iscollectable(obj) || \ + (righttt(obj) && (L == NULL || !isdead(G(L),gcvalue(obj))))) + + +/* Macros to set values */ +#define settt_(o,t) ((o)->tt_=(t)) + +#define setfltvalue(obj,x) \ + { TValue *io=(obj); val_(io).n=(x); settt_(io, LUA_TNUMFLT); } + +#define chgfltvalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisfloat(io)); val_(io).n=(x); } + +#define setivalue(obj,x) \ + { TValue *io=(obj); val_(io).i=(x); settt_(io, LUA_TNUMINT); } + +#define chgivalue(obj,x) \ + { TValue *io=(obj); lua_assert(ttisinteger(io)); val_(io).i=(x); } + +#define setnilvalue(obj) settt_(obj, LUA_TNIL) + +#define setfvalue(obj,x) \ + { TValue *io=(obj); val_(io).f=(x); settt_(io, LUA_TLCF); } + +#define setpvalue(obj,x) \ + { TValue *io=(obj); val_(io).p=(x); settt_(io, LUA_TLIGHTUSERDATA); } + +#define setbvalue(obj,x) \ + { TValue *io=(obj); val_(io).b=(x); settt_(io, LUA_TBOOLEAN); } + +#define setgcovalue(L,obj,x) \ + { TValue *io = (obj); GCObject *i_g=(x); \ + val_(io).gc = i_g; settt_(io, ctb(i_g->tt)); } + +#define setsvalue(L,obj,x) \ + { TValue *io = (obj); TString *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(x_->tt)); \ + checkliveness(L,io); } + +#define setuvalue(L,obj,x) \ + { TValue *io = (obj); Udata *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TUSERDATA)); \ + checkliveness(L,io); } + +#define setthvalue(L,obj,x) \ + { TValue *io = (obj); lua_State *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTHREAD)); \ + checkliveness(L,io); } + +#define setclLvalue(L,obj,x) \ + { TValue *io = (obj); LClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TLCL)); \ + checkliveness(L,io); } + +#define setclCvalue(L,obj,x) \ + { TValue *io = (obj); CClosure *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TCCL)); \ + checkliveness(L,io); } + +#define sethvalue(L,obj,x) \ + { TValue *io = (obj); Table *x_ = (x); \ + val_(io).gc = obj2gco(x_); settt_(io, ctb(LUA_TTABLE)); \ + checkliveness(L,io); } + +#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) + + + +#define setobj(L,obj1,obj2) \ + { TValue *io1=(obj1); *io1 = *(obj2); \ + (void)L; checkliveness(L,io1); } + + +/* +** different types of assignments, according to destination +*/ + +/* from stack to (same) stack */ +#define setobjs2s setobj +/* to stack (not from same stack) */ +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue +/* from table to same table */ +#define setobjt2t setobj +/* to new object */ +#define setobj2n setobj +#define setsvalue2n setsvalue + +/* to table (define it as an expression to be used in macros) */ +#define setobj2t(L,o1,o2) ((void)L, *(o1)=*(o2), checkliveness(L,(o1))) + + + + +/* +** {====================================================== +** types and prototypes +** ======================================================= +*/ + + +typedef TValue *StkId; /* index to stack elements */ + + + + +/* +** Header for string value; string bytes follow the end of this structure +** (aligned according to 'UTString'; see next). +*/ +typedef struct TString { + CommonHeader; + lu_byte extra; /* reserved words for short strings; "has hash" for longs */ + lu_byte shrlen; /* length for short strings */ + unsigned int hash; + union { + size_t lnglen; /* length for long strings */ + struct TString *hnext; /* linked list for hash table */ + } u; +} TString; + + +/* +** Ensures that address after this type is always fully aligned. +*/ +typedef union UTString { + L_Umaxalign dummy; /* ensures maximum alignment for strings */ + TString tsv; +} UTString; + + +/* +** Get the actual string (array of bytes) from a 'TString'. +** (Access to 'extra' ensures that value is really a 'TString'.) +*/ +#define getstr(ts) \ + check_exp(sizeof((ts)->extra), cast(char *, (ts)) + sizeof(UTString)) + + +/* get the actual string (array of bytes) from a Lua value */ +#define svalue(o) getstr(tsvalue(o)) + +/* get string length from 'TString *s' */ +#define tsslen(s) ((s)->tt == LUA_TSHRSTR ? (s)->shrlen : (s)->u.lnglen) + +/* get string length from 'TValue *o' */ +#define vslen(o) tsslen(tsvalue(o)) + + +/* +** Header for userdata; memory area follows the end of this structure +** (aligned according to 'UUdata'; see next). +*/ +typedef struct Udata { + CommonHeader; + lu_byte ttuv_; /* user value's tag */ + struct Table *metatable; + size_t len; /* number of bytes */ + union Value user_; /* user value */ +} Udata; + + +/* +** Ensures that address after this type is always fully aligned. +*/ +typedef union UUdata { + L_Umaxalign dummy; /* ensures maximum alignment for 'local' udata */ + Udata uv; +} UUdata; + + +/* +** Get the address of memory block inside 'Udata'. +** (Access to 'ttuv_' ensures that value is really a 'Udata'.) +*/ +#define getudatamem(u) \ + check_exp(sizeof((u)->ttuv_), (cast(char*, (u)) + sizeof(UUdata))) + +#define setuservalue(L,u,o) \ + { const TValue *io=(o); Udata *iu = (u); \ + iu->user_ = io->value_; iu->ttuv_ = rttype(io); \ + checkliveness(L,io); } + + +#define getuservalue(L,u,o) \ + { TValue *io=(o); const Udata *iu = (u); \ + io->value_ = iu->user_; settt_(io, iu->ttuv_); \ + checkliveness(L,io); } + + +/* +** Description of an upvalue for function prototypes +*/ +typedef struct Upvaldesc { + TString *name; /* upvalue name (for debug information) */ + lu_byte instack; /* whether it is in stack (register) */ + lu_byte idx; /* index of upvalue (in stack or in outer function's list) */ +} Upvaldesc; + + +/* +** Description of a local variable for function prototypes +** (used for debug information) +*/ +typedef struct LocVar { + TString *varname; + int startpc; /* first point where variable is active */ + int endpc; /* first point where variable is dead */ +} LocVar; + + +/* +** Function Prototypes +*/ +typedef struct Proto { + CommonHeader; + lu_byte numparams; /* number of fixed parameters */ + lu_byte is_vararg; + lu_byte maxstacksize; /* number of registers needed by this function */ + int sizeupvalues; /* size of 'upvalues' */ + int sizek; /* size of 'k' */ + int sizecode; + int sizelineinfo; + int sizep; /* size of 'p' */ + int sizelocvars; + int linedefined; /* debug information */ + int lastlinedefined; /* debug information */ + TValue *k; /* constants used by the function */ + Instruction *code; /* opcodes */ + struct Proto **p; /* functions defined inside the function */ + int *lineinfo; /* map from opcodes to source lines (debug information) */ + LocVar *locvars; /* information about local variables (debug information) */ + Upvaldesc *upvalues; /* upvalue information */ + struct LClosure *cache; /* last-created closure with this prototype */ + TString *source; /* used for debug information */ + GCObject *gclist; +} Proto; + + + +/* +** Lua Upvalues +*/ +typedef struct UpVal UpVal; + + +/* +** Closures +*/ + +#define ClosureHeader \ + CommonHeader; lu_byte nupvalues; GCObject *gclist + +typedef struct CClosure { + ClosureHeader; + lua_CFunction f; + TValue upvalue[1]; /* list of upvalues */ +} CClosure; + + +typedef struct LClosure { + ClosureHeader; + struct Proto *p; + UpVal *upvals[1]; /* list of upvalues */ +} LClosure; + + +typedef union Closure { + CClosure c; + LClosure l; +} Closure; + + +#define isLfunction(o) ttisLclosure(o) + +#define getproto(o) (clLvalue(o)->p) + + +/* +** Tables +*/ + +typedef union TKey { + struct { + TValuefields; + int next; /* for chaining (offset for next node) */ + } nk; + TValue tvk; +} TKey; + + +/* copy a value into a key without messing up field 'next' */ +#define setnodekey(L,key,obj) \ + { TKey *k_=(key); const TValue *io_=(obj); \ + k_->nk.value_ = io_->value_; k_->nk.tt_ = io_->tt_; \ + (void)L; checkliveness(L,io_); } + + +typedef struct Node { + TValue i_val; + TKey i_key; +} Node; + + +typedef struct Table { + CommonHeader; + lu_byte flags; /* 1<

lsizenode)) + + +/* +** (address of) a fixed nil value +*/ +#define luaO_nilobject (&luaO_nilobject_) + + +LUAI_DDEC const TValue luaO_nilobject_; + +/* size of buffer for 'luaO_utf8esc' function */ +#define UTF8BUFFSZ 8 + +LUAI_FUNC int luaO_int2fb (unsigned int x); +LUAI_FUNC int luaO_fb2int (int x); +LUAI_FUNC int luaO_utf8esc (char *buff, unsigned long x); +LUAI_FUNC int luaO_ceillog2 (unsigned int x); +LUAI_FUNC void luaO_arith (lua_State *L, int op, const TValue *p1, + const TValue *p2, TValue *res); +LUAI_FUNC size_t luaO_str2num (const char *s, TValue *o); +LUAI_FUNC int luaO_hexavalue (int c); +LUAI_FUNC void luaO_tostring (lua_State *L, StkId obj); +LUAI_FUNC const char *luaO_pushvfstring (lua_State *L, const char *fmt, + va_list argp); +LUAI_FUNC const char *luaO_pushfstring (lua_State *L, const char *fmt, ...); +LUAI_FUNC void luaO_chunkid (char *out, const char *source, size_t len); + + +#endif + diff --git a/src/lua/lopcodes.c b/src/lua/lopcodes.c new file mode 100644 index 000000000000..5ca3eb261a48 --- /dev/null +++ b/src/lua/lopcodes.c @@ -0,0 +1,124 @@ +/* +** $Id: lopcodes.c,v 1.55.1.1 2017/04/19 17:20:42 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#define lopcodes_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lopcodes.h" + + +/* ORDER OP */ + +LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { + "MOVE", + "LOADK", + "LOADKX", + "LOADBOOL", + "LOADNIL", + "GETUPVAL", + "GETTABUP", + "GETTABLE", + "SETTABUP", + "SETUPVAL", + "SETTABLE", + "NEWTABLE", + "SELF", + "ADD", + "SUB", + "MUL", + "MOD", + "POW", + "DIV", + "IDIV", + "BAND", + "BOR", + "BXOR", + "SHL", + "SHR", + "UNM", + "BNOT", + "NOT", + "LEN", + "CONCAT", + "JMP", + "EQ", + "LT", + "LE", + "TEST", + "TESTSET", + "CALL", + "TAILCALL", + "RETURN", + "FORLOOP", + "FORPREP", + "TFORCALL", + "TFORLOOP", + "SETLIST", + "CLOSURE", + "VARARG", + "EXTRAARG", + NULL +}; + + +#define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) + +LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_IDIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BAND */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BOR */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_BXOR */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SHR */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_BNOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ + ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ +}; + diff --git a/src/lua/lopcodes.h b/src/lua/lopcodes.h new file mode 100644 index 000000000000..6feaa1cd07aa --- /dev/null +++ b/src/lua/lopcodes.h @@ -0,0 +1,297 @@ +/* +** $Id: lopcodes.h,v 1.149.1.1 2017/04/19 17:20:42 roberto Exp $ +** Opcodes for Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lopcodes_h +#define lopcodes_h + +#include "llimits.h" + + +/*=========================================================================== + We assume that instructions are unsigned numbers. + All instructions have an opcode in the first 6 bits. + Instructions can have the following fields: + 'A' : 8 bits + 'B' : 9 bits + 'C' : 9 bits + 'Ax' : 26 bits ('A', 'B', and 'C' together) + 'Bx' : 18 bits ('B' and 'C' together) + 'sBx' : signed Bx + + A signed argument is represented in excess K; that is, the number + value is the unsigned value minus K. K is exactly the maximum value + for that argument (so that -max is represented by 0, and +max is + represented by 2*max), which is half the maximum for the corresponding + unsigned argument. +===========================================================================*/ + + +enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ + + +/* +** size and position of opcode arguments. +*/ +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 +#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) + +#define SIZE_OP 6 + +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C +#define POS_Ax POS_A + + +/* +** limits for opcode arguments. +** we use (signed) int to manipulate most arguments, +** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) +*/ +#if SIZE_Bx < LUAI_BITSINT-1 +#define MAXARG_Bx ((1<>1) /* 'sBx' is signed */ +#else +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT +#endif + +#if SIZE_Ax < LUAI_BITSINT-1 +#define MAXARG_Ax ((1<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>pos) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ + ((cast(Instruction, v)<> RK(C) */ +OP_UNM,/* A B R(A) := -R(B) */ +OP_BNOT,/* A B R(A) := ~R(B) */ +OP_NOT,/* A B R(A) := not R(B) */ +OP_LEN,/* A B R(A) := length of R(B) */ + +OP_CONCAT,/* A B C R(A) := R(B).. ... ..R(C) */ + +OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A - 1) */ +OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ + +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ + +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ + +OP_FORLOOP,/* A sBx R(A)+=R(A+2); + if R(A) > 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) + + +LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ + + +/* number of list items to accumulate before a SETLIST instruction */ +#define LFIELDS_PER_FLUSH 50 + + +#endif diff --git a/src/lua/loslib.c b/src/lua/loslib.c new file mode 100644 index 000000000000..de590c6b717a --- /dev/null +++ b/src/lua/loslib.c @@ -0,0 +1,409 @@ +/* +** $Id: loslib.c,v 1.65.1.1 2017/04/19 17:29:57 roberto Exp $ +** Standard Operating System library +** See Copyright Notice in lua.h +*/ + +#define loslib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** {================================================================== +** List of valid conversion specifiers for the 'strftime' function; +** options are grouped by length; group of length 2 start with '||'. +** =================================================================== +*/ +#if !defined(LUA_STRFTIMEOPTIONS) /* { */ + +/* options for ANSI C 89 (only 1-char options) */ +#define L_STRFTIMEC89 "aAbBcdHIjmMpSUwWxXyYZ%" + +/* options for ISO C 99 and POSIX */ +#define L_STRFTIMEC99 "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%" \ + "||" "EcECExEXEyEY" "OdOeOHOIOmOMOSOuOUOVOwOWOy" /* two-char options */ + +/* options for Windows */ +#define L_STRFTIMEWIN "aAbBcdHIjmMpSUwWxXyYzZ%" \ + "||" "#c#x#d#H#I#j#m#M#S#U#w#W#y#Y" /* two-char options */ + +#if defined(LUA_USE_WINDOWS) +#define LUA_STRFTIMEOPTIONS L_STRFTIMEWIN +#elif defined(LUA_USE_C89) +#define LUA_STRFTIMEOPTIONS L_STRFTIMEC89 +#else /* C99 specification */ +#define LUA_STRFTIMEOPTIONS L_STRFTIMEC99 +#endif + +#endif /* } */ +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for time-related stuff +** =================================================================== +*/ + +#if !defined(l_time_t) /* { */ +/* +** type to represent time_t in Lua +*/ +#define l_timet lua_Integer +#define l_pushtime(L,t) lua_pushinteger(L,(lua_Integer)(t)) + +static time_t l_checktime (lua_State *L, int arg) { + lua_Integer t = luaL_checkinteger(L, arg); + luaL_argcheck(L, (time_t)t == t, arg, "time out-of-bounds"); + return (time_t)t; +} + +#endif /* } */ + + +#if !defined(l_gmtime) /* { */ +/* +** By default, Lua uses gmtime/localtime, except when POSIX is available, +** where it uses gmtime_r/localtime_r +*/ + +#if defined(LUA_USE_POSIX) /* { */ + +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) + +#else /* }{ */ + +/* ISO C definitions */ +#define l_gmtime(t,r) ((void)(r)->tm_sec, gmtime(t)) +#define l_localtime(t,r) ((void)(r)->tm_sec, localtime(t)) + +#endif /* } */ + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Configuration for 'tmpnam': +** By default, Lua uses tmpnam except when POSIX is available, where +** it uses mkstemp. +** =================================================================== +*/ +#if !defined(lua_tmpnam) /* { */ + +#if defined(LUA_USE_POSIX) /* { */ + +#include + +#define LUA_TMPNAMBUFSIZE 32 + +#if !defined(LUA_TMPNAMTEMPLATE) +#define LUA_TMPNAMTEMPLATE "/tmp/lua_XXXXXX" +#endif + +#define lua_tmpnam(b,e) { \ + strcpy(b, LUA_TMPNAMTEMPLATE); \ + e = mkstemp(b); \ + if (e != -1) close(e); \ + e = (e == -1); } + +#else /* }{ */ + +/* ISO C definitions */ +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } + +#endif /* } */ + +#endif /* } */ +/* }================================================================== */ + + + + +static int os_execute (lua_State *L) { + const char *cmd = luaL_optstring(L, 1, NULL); + int stat = system(cmd); + if (cmd != NULL) + return luaL_execresult(L, stat); + else { + lua_pushboolean(L, stat); /* true if there is a shell */ + return 1; + } +} + + +static int os_remove (lua_State *L) { + const char *filename = luaL_checkstring(L, 1); + return luaL_fileresult(L, remove(filename) == 0, filename); +} + + +static int os_rename (lua_State *L) { + const char *fromname = luaL_checkstring(L, 1); + const char *toname = luaL_checkstring(L, 2); + return luaL_fileresult(L, rename(fromname, toname) == 0, NULL); +} + + +static int os_tmpname (lua_State *L) { + char buff[LUA_TMPNAMBUFSIZE]; + int err; + lua_tmpnam(buff, err); + if (err) + return luaL_error(L, "unable to generate a unique filename"); + lua_pushstring(L, buff); + return 1; +} + + +static int os_getenv (lua_State *L) { + lua_pushstring(L, getenv(luaL_checkstring(L, 1))); /* if NULL push nil */ + return 1; +} + + +static int os_clock (lua_State *L) { + lua_pushnumber(L, ((lua_Number)clock())/(lua_Number)CLOCKS_PER_SEC); + return 1; +} + + +/* +** {====================================================== +** Time/Date operations +** { year=%Y, month=%m, day=%d, hour=%H, min=%M, sec=%S, +** wday=%w+1, yday=%j, isdst=? } +** ======================================================= +*/ + +static void setfield (lua_State *L, const char *key, int value) { + lua_pushinteger(L, value); + lua_setfield(L, -2, key); +} + +static void setboolfield (lua_State *L, const char *key, int value) { + if (value < 0) /* undefined? */ + return; /* does not set field */ + lua_pushboolean(L, value); + lua_setfield(L, -2, key); +} + + +/* +** Set all fields from structure 'tm' in the table on top of the stack +*/ +static void setallfields (lua_State *L, struct tm *stm) { + setfield(L, "sec", stm->tm_sec); + setfield(L, "min", stm->tm_min); + setfield(L, "hour", stm->tm_hour); + setfield(L, "day", stm->tm_mday); + setfield(L, "month", stm->tm_mon + 1); + setfield(L, "year", stm->tm_year + 1900); + setfield(L, "wday", stm->tm_wday + 1); + setfield(L, "yday", stm->tm_yday + 1); + setboolfield(L, "isdst", stm->tm_isdst); +} + + +static int getboolfield (lua_State *L, const char *key) { + int res; + res = (lua_getfield(L, -1, key) == LUA_TNIL) ? -1 : lua_toboolean(L, -1); + lua_pop(L, 1); + return res; +} + + +/* maximum value for date fields (to avoid arithmetic overflows with 'int') */ +#if !defined(L_MAXDATEFIELD) +#define L_MAXDATEFIELD (INT_MAX / 2) +#endif + +static int getfield (lua_State *L, const char *key, int d, int delta) { + int isnum; + int t = lua_getfield(L, -1, key); /* get field and its type */ + lua_Integer res = lua_tointegerx(L, -1, &isnum); + if (!isnum) { /* field is not an integer? */ + if (t != LUA_TNIL) /* some other value? */ + return luaL_error(L, "field '%s' is not an integer", key); + else if (d < 0) /* absent field; no default? */ + return luaL_error(L, "field '%s' missing in date table", key); + res = d; + } + else { + if (!(-L_MAXDATEFIELD <= res && res <= L_MAXDATEFIELD)) + return luaL_error(L, "field '%s' is out-of-bound", key); + res -= delta; + } + lua_pop(L, 1); + return (int)res; +} + + +static const char *checkoption (lua_State *L, const char *conv, + ptrdiff_t convlen, char *buff) { + const char *option = LUA_STRFTIMEOPTIONS; + int oplen = 1; /* length of options being checked */ + for (; *option != '\0' && oplen <= convlen; option += oplen) { + if (*option == '|') /* next block? */ + oplen++; /* will check options with next length (+1) */ + else if (memcmp(conv, option, oplen) == 0) { /* match? */ + memcpy(buff, conv, oplen); /* copy valid option to buffer */ + buff[oplen] = '\0'; + return conv + oplen; /* return next item */ + } + } + luaL_argerror(L, 1, + lua_pushfstring(L, "invalid conversion specifier '%%%s'", conv)); + return conv; /* to avoid warnings */ +} + + +/* maximum size for an individual 'strftime' item */ +#define SIZETIMEFMT 250 + + +static int os_date (lua_State *L) { + size_t slen; + const char *s = luaL_optlstring(L, 1, "%c", &slen); + time_t t = luaL_opt(L, l_checktime, 2, time(NULL)); + const char *se = s + slen; /* 's' end */ + struct tm tmr, *stm; + if (*s == '!') { /* UTC? */ + stm = l_gmtime(&t, &tmr); + s++; /* skip '!' */ + } + else + stm = l_localtime(&t, &tmr); + if (stm == NULL) /* invalid date? */ + return luaL_error(L, + "time result cannot be represented in this installation"); + if (strcmp(s, "*t") == 0) { + lua_createtable(L, 0, 9); /* 9 = number of fields */ + setallfields(L, stm); + } + else { + char cc[4]; /* buffer for individual conversion specifiers */ + luaL_Buffer b; + cc[0] = '%'; + luaL_buffinit(L, &b); + while (s < se) { + if (*s != '%') /* not a conversion specifier? */ + luaL_addchar(&b, *s++); + else { + size_t reslen; + char *buff = luaL_prepbuffsize(&b, SIZETIMEFMT); + s++; /* skip '%' */ + s = checkoption(L, s, se - s, cc + 1); /* copy specifier to 'cc' */ + reslen = strftime(buff, SIZETIMEFMT, cc, stm); + luaL_addsize(&b, reslen); + } + } + luaL_pushresult(&b); + } + return 1; +} + + +static int os_time (lua_State *L) { + time_t t; + if (lua_isnoneornil(L, 1)) /* called without args? */ + t = time(NULL); /* get current time */ + else { + struct tm ts; + luaL_checktype(L, 1, LUA_TTABLE); + lua_settop(L, 1); /* make sure table is at the top */ + ts.tm_sec = getfield(L, "sec", 0, 0); + ts.tm_min = getfield(L, "min", 0, 0); + ts.tm_hour = getfield(L, "hour", 12, 0); + ts.tm_mday = getfield(L, "day", -1, 0); + ts.tm_mon = getfield(L, "month", -1, 1); + ts.tm_year = getfield(L, "year", -1, 1900); + ts.tm_isdst = getboolfield(L, "isdst"); + t = mktime(&ts); + setallfields(L, &ts); /* update fields with normalized values */ + } + if (t != (time_t)(l_timet)t || t == (time_t)(-1)) + return luaL_error(L, + "time result cannot be represented in this installation"); + l_pushtime(L, t); + return 1; +} + + +static int os_difftime (lua_State *L) { + time_t t1 = l_checktime(L, 1); + time_t t2 = l_checktime(L, 2); + lua_pushnumber(L, (lua_Number)difftime(t1, t2)); + return 1; +} + +/* }====================================================== */ + + +static int os_setlocale (lua_State *L) { + static const int cat[] = {LC_ALL, LC_COLLATE, LC_CTYPE, LC_MONETARY, + LC_NUMERIC, LC_TIME}; + static const char *const catnames[] = {"all", "collate", "ctype", "monetary", + "numeric", "time", NULL}; + const char *l = luaL_optstring(L, 1, NULL); + int op = luaL_checkoption(L, 2, "all", catnames); + lua_pushstring(L, setlocale(cat[op], l)); + return 1; +} + + +static int os_exit (lua_State *L) { + int status; + if (lua_isboolean(L, 1)) + status = (lua_toboolean(L, 1) ? EXIT_SUCCESS : EXIT_FAILURE); + else + status = (int)luaL_optinteger(L, 1, EXIT_SUCCESS); + if (lua_toboolean(L, 2)) + lua_close(L); + if (L) exit(status); /* 'if' to avoid warnings for unreachable 'return' */ + return 0; +} + + +static const luaL_Reg syslib[] = { + {"clock", os_clock}, + {"date", os_date}, + {"difftime", os_difftime}, + {"execute", os_execute}, + {"exit", os_exit}, + {"getenv", os_getenv}, + {"remove", os_remove}, + {"rename", os_rename}, + {"setlocale", os_setlocale}, + {"time", os_time}, + {"tmpname", os_tmpname}, + {NULL, NULL} +}; + +/* }====================================================== */ + + + +LUAMOD_API int luaopen_os (lua_State *L) { + luaL_newlib(L, syslib); + return 1; +} + diff --git a/src/lua/lparser.c b/src/lua/lparser.c new file mode 100644 index 000000000000..2f41e00b803d --- /dev/null +++ b/src/lua/lparser.c @@ -0,0 +1,1653 @@ +/* +** $Id: lparser.c,v 2.155.1.2 2017/04/29 18:11:40 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#define lparser_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "lcode.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "llex.h" +#include "lmem.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lparser.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" + + + +/* maximum number of local variables per function (must be smaller + than 250, due to the bytecode format) */ +#define MAXVARS 200 + + +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) + + +/* because all strings are unified by the scanner, the parser + can use pointer equality for string equality */ +#define eqstr(a,b) ((a) == (b)) + + +/* +** nodes for block list (list of active blocks) +*/ +typedef struct BlockCnt { + struct BlockCnt *previous; /* chain */ + int firstlabel; /* index of first label in this block */ + int firstgoto; /* index of first pending goto in this block */ + lu_byte nactvar; /* # active locals outside the block */ + lu_byte upval; /* true if some variable in the block is an upvalue */ + lu_byte isloop; /* true if 'block' is a loop */ +} BlockCnt; + + + +/* +** prototypes for recursive non-terminal functions +*/ +static void statement (LexState *ls); +static void expr (LexState *ls, expdesc *v); + + +/* semantic error */ +static l_noret semerror (LexState *ls, const char *msg) { + ls->t.token = 0; /* remove "near " from final message */ + luaX_syntaxerror(ls, msg); +} + + +static l_noret error_expected (LexState *ls, int token) { + luaX_syntaxerror(ls, + luaO_pushfstring(ls->L, "%s expected", luaX_token2str(ls, token))); +} + + +static l_noret errorlimit (FuncState *fs, int limit, const char *what) { + lua_State *L = fs->ls->L; + const char *msg; + int line = fs->f->linedefined; + const char *where = (line == 0) + ? "main function" + : luaO_pushfstring(L, "function at line %d", line); + msg = luaO_pushfstring(L, "too many %s (limit is %d) in %s", + what, limit, where); + luaX_syntaxerror(fs->ls, msg); +} + + +static void checklimit (FuncState *fs, int v, int l, const char *what) { + if (v > l) errorlimit(fs, l, what); +} + + +static int testnext (LexState *ls, int c) { + if (ls->t.token == c) { + luaX_next(ls); + return 1; + } + else return 0; +} + + +static void check (LexState *ls, int c) { + if (ls->t.token != c) + error_expected(ls, c); +} + + +static void checknext (LexState *ls, int c) { + check(ls, c); + luaX_next(ls); +} + + +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } + + + +static void check_match (LexState *ls, int what, int who, int where) { + if (!testnext(ls, what)) { + if (where == ls->linenumber) + error_expected(ls, what); + else { + luaX_syntaxerror(ls, luaO_pushfstring(ls->L, + "%s expected (to close %s at line %d)", + luaX_token2str(ls, what), luaX_token2str(ls, who), where)); + } + } +} + + +static TString *str_checkname (LexState *ls) { + TString *ts; + check(ls, TK_NAME); + ts = ls->t.seminfo.ts; + luaX_next(ls); + return ts; +} + + +static void init_exp (expdesc *e, expkind k, int i) { + e->f = e->t = NO_JUMP; + e->k = k; + e->u.info = i; +} + + +static void codestring (LexState *ls, expdesc *e, TString *s) { + init_exp(e, VK, luaK_stringK(ls->fs, s)); +} + + +static void checkname (LexState *ls, expdesc *e) { + codestring(ls, e, str_checkname(ls)); +} + + +static int registerlocalvar (LexState *ls, TString *varname) { + FuncState *fs = ls->fs; + Proto *f = fs->f; + int oldsize = f->sizelocvars; + luaM_growvector(ls->L, f->locvars, fs->nlocvars, f->sizelocvars, + LocVar, SHRT_MAX, "local variables"); + while (oldsize < f->sizelocvars) + f->locvars[oldsize++].varname = NULL; + f->locvars[fs->nlocvars].varname = varname; + luaC_objbarrier(ls->L, f, varname); + return fs->nlocvars++; +} + + +static void new_localvar (LexState *ls, TString *name) { + FuncState *fs = ls->fs; + Dyndata *dyd = ls->dyd; + int reg = registerlocalvar(ls, name); + checklimit(fs, dyd->actvar.n + 1 - fs->firstlocal, + MAXVARS, "local variables"); + luaM_growvector(ls->L, dyd->actvar.arr, dyd->actvar.n + 1, + dyd->actvar.size, Vardesc, MAX_INT, "local variables"); + dyd->actvar.arr[dyd->actvar.n++].idx = cast(short, reg); +} + + +static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { + new_localvar(ls, luaX_newstring(ls, name, sz)); +} + +#define new_localvarliteral(ls,v) \ + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + + +static LocVar *getlocvar (FuncState *fs, int i) { + int idx = fs->ls->dyd->actvar.arr[fs->firstlocal + i].idx; + lua_assert(idx < fs->nlocvars); + return &fs->f->locvars[idx]; +} + + +static void adjustlocalvars (LexState *ls, int nvars) { + FuncState *fs = ls->fs; + fs->nactvar = cast_byte(fs->nactvar + nvars); + for (; nvars; nvars--) { + getlocvar(fs, fs->nactvar - nvars)->startpc = fs->pc; + } +} + + +static void removevars (FuncState *fs, int tolevel) { + fs->ls->dyd->actvar.n -= (fs->nactvar - tolevel); + while (fs->nactvar > tolevel) + getlocvar(fs, --fs->nactvar)->endpc = fs->pc; +} + + +static int searchupvalue (FuncState *fs, TString *name) { + int i; + Upvaldesc *up = fs->f->upvalues; + for (i = 0; i < fs->nups; i++) { + if (eqstr(up[i].name, name)) return i; + } + return -1; /* not found */ +} + + +static int newupvalue (FuncState *fs, TString *name, expdesc *v) { + Proto *f = fs->f; + int oldsize = f->sizeupvalues; + checklimit(fs, fs->nups + 1, MAXUPVAL, "upvalues"); + luaM_growvector(fs->ls->L, f->upvalues, fs->nups, f->sizeupvalues, + Upvaldesc, MAXUPVAL, "upvalues"); + while (oldsize < f->sizeupvalues) + f->upvalues[oldsize++].name = NULL; + f->upvalues[fs->nups].instack = (v->k == VLOCAL); + f->upvalues[fs->nups].idx = cast_byte(v->u.info); + f->upvalues[fs->nups].name = name; + luaC_objbarrier(fs->ls->L, f, name); + return fs->nups++; +} + + +static int searchvar (FuncState *fs, TString *n) { + int i; + for (i = cast_int(fs->nactvar) - 1; i >= 0; i--) { + if (eqstr(n, getlocvar(fs, i)->varname)) + return i; + } + return -1; /* not found */ +} + + +/* + Mark block where variable at given level was defined + (to emit close instructions later). +*/ +static void markupval (FuncState *fs, int level) { + BlockCnt *bl = fs->bl; + while (bl->nactvar > level) + bl = bl->previous; + bl->upval = 1; +} + + +/* + Find variable with given name 'n'. If it is an upvalue, add this + upvalue into all intermediate functions. +*/ +static void singlevaraux (FuncState *fs, TString *n, expdesc *var, int base) { + if (fs == NULL) /* no more levels? */ + init_exp(var, VVOID, 0); /* default is global */ + else { + int v = searchvar(fs, n); /* look up locals at current level */ + if (v >= 0) { /* found? */ + init_exp(var, VLOCAL, v); /* variable is local */ + if (!base) + markupval(fs, v); /* local will be used as an upval */ + } + else { /* not found as local at current level; try upvalues */ + int idx = searchupvalue(fs, n); /* try existing upvalues */ + if (idx < 0) { /* not found? */ + singlevaraux(fs->prev, n, var, 0); /* try upper levels */ + if (var->k == VVOID) /* not found? */ + return; /* it is a global */ + /* else was LOCAL or UPVAL */ + idx = newupvalue(fs, n, var); /* will be a new upvalue */ + } + init_exp(var, VUPVAL, idx); /* new or old upvalue */ + } + } +} + + +static void singlevar (LexState *ls, expdesc *var) { + TString *varname = str_checkname(ls); + FuncState *fs = ls->fs; + singlevaraux(fs, varname, var, 1); + if (var->k == VVOID) { /* global name? */ + expdesc key; + singlevaraux(fs, ls->envn, var, 1); /* get environment variable */ + lua_assert(var->k != VVOID); /* this one must exist */ + codestring(ls, &key, varname); /* key is variable name */ + luaK_indexed(fs, var, &key); /* env[varname] */ + } +} + + +static void adjust_assign (LexState *ls, int nvars, int nexps, expdesc *e) { + FuncState *fs = ls->fs; + int extra = nvars - nexps; + if (hasmultret(e->k)) { + extra++; /* includes call itself */ + if (extra < 0) extra = 0; + luaK_setreturns(fs, e, extra); /* last exp. provides the difference */ + if (extra > 1) luaK_reserveregs(fs, extra-1); + } + else { + if (e->k != VVOID) luaK_exp2nextreg(fs, e); /* close last expression */ + if (extra > 0) { + int reg = fs->freereg; + luaK_reserveregs(fs, extra); + luaK_nil(fs, reg, extra); + } + } + if (nexps > nvars) + ls->fs->freereg -= nexps - nvars; /* remove extra values */ +} + + +static void enterlevel (LexState *ls) { + lua_State *L = ls->L; + ++L->nCcalls; + checklimit(ls->fs, L->nCcalls, LUAI_MAXCCALLS, "C levels"); +} + + +#define leavelevel(ls) ((ls)->L->nCcalls--) + + +static void closegoto (LexState *ls, int g, Labeldesc *label) { + int i; + FuncState *fs = ls->fs; + Labellist *gl = &ls->dyd->gt; + Labeldesc *gt = &gl->arr[g]; + lua_assert(eqstr(gt->name, label->name)); + if (gt->nactvar < label->nactvar) { + TString *vname = getlocvar(fs, gt->nactvar)->varname; + const char *msg = luaO_pushfstring(ls->L, + " at line %d jumps into the scope of local '%s'", + getstr(gt->name), gt->line, getstr(vname)); + semerror(ls, msg); + } + luaK_patchlist(fs, gt->pc, label->pc); + /* remove goto from pending list */ + for (i = g; i < gl->n - 1; i++) + gl->arr[i] = gl->arr[i + 1]; + gl->n--; +} + + +/* +** try to close a goto with existing labels; this solves backward jumps +*/ +static int findlabel (LexState *ls, int g) { + int i; + BlockCnt *bl = ls->fs->bl; + Dyndata *dyd = ls->dyd; + Labeldesc *gt = &dyd->gt.arr[g]; + /* check labels in current block for a match */ + for (i = bl->firstlabel; i < dyd->label.n; i++) { + Labeldesc *lb = &dyd->label.arr[i]; + if (eqstr(lb->name, gt->name)) { /* correct label? */ + if (gt->nactvar > lb->nactvar && + (bl->upval || dyd->label.n > bl->firstlabel)) + luaK_patchclose(ls->fs, gt->pc, lb->nactvar); + closegoto(ls, g, lb); /* close it */ + return 1; + } + } + return 0; /* label not found; cannot close goto */ +} + + +static int newlabelentry (LexState *ls, Labellist *l, TString *name, + int line, int pc) { + int n = l->n; + luaM_growvector(ls->L, l->arr, n, l->size, + Labeldesc, SHRT_MAX, "labels/gotos"); + l->arr[n].name = name; + l->arr[n].line = line; + l->arr[n].nactvar = ls->fs->nactvar; + l->arr[n].pc = pc; + l->n = n + 1; + return n; +} + + +/* +** check whether new label 'lb' matches any pending gotos in current +** block; solves forward jumps +*/ +static void findgotos (LexState *ls, Labeldesc *lb) { + Labellist *gl = &ls->dyd->gt; + int i = ls->fs->bl->firstgoto; + while (i < gl->n) { + if (eqstr(gl->arr[i].name, lb->name)) + closegoto(ls, i, lb); + else + i++; + } +} + + +/* +** export pending gotos to outer level, to check them against +** outer labels; if the block being exited has upvalues, and +** the goto exits the scope of any variable (which can be the +** upvalue), close those variables being exited. +*/ +static void movegotosout (FuncState *fs, BlockCnt *bl) { + int i = bl->firstgoto; + Labellist *gl = &fs->ls->dyd->gt; + /* correct pending gotos to current block and try to close it + with visible labels */ + while (i < gl->n) { + Labeldesc *gt = &gl->arr[i]; + if (gt->nactvar > bl->nactvar) { + if (bl->upval) + luaK_patchclose(fs, gt->pc, bl->nactvar); + gt->nactvar = bl->nactvar; + } + if (!findlabel(fs->ls, i)) + i++; /* move to next one */ + } +} + + +static void enterblock (FuncState *fs, BlockCnt *bl, lu_byte isloop) { + bl->isloop = isloop; + bl->nactvar = fs->nactvar; + bl->firstlabel = fs->ls->dyd->label.n; + bl->firstgoto = fs->ls->dyd->gt.n; + bl->upval = 0; + bl->previous = fs->bl; + fs->bl = bl; + lua_assert(fs->freereg == fs->nactvar); +} + + +/* +** create a label named 'break' to resolve break statements +*/ +static void breaklabel (LexState *ls) { + TString *n = luaS_new(ls->L, "break"); + int l = newlabelentry(ls, &ls->dyd->label, n, 0, ls->fs->pc); + findgotos(ls, &ls->dyd->label.arr[l]); +} + +/* +** generates an error for an undefined 'goto'; choose appropriate +** message when label name is a reserved word (which can only be 'break') +*/ +static l_noret undefgoto (LexState *ls, Labeldesc *gt) { + const char *msg = isreserved(gt->name) + ? "<%s> at line %d not inside a loop" + : "no visible label '%s' for at line %d"; + msg = luaO_pushfstring(ls->L, msg, getstr(gt->name), gt->line); + semerror(ls, msg); +} + + +static void leaveblock (FuncState *fs) { + BlockCnt *bl = fs->bl; + LexState *ls = fs->ls; + if (bl->previous && bl->upval) { + /* create a 'jump to here' to close upvalues */ + int j = luaK_jump(fs); + luaK_patchclose(fs, j, bl->nactvar); + luaK_patchtohere(fs, j); + } + if (bl->isloop) + breaklabel(ls); /* close pending breaks */ + fs->bl = bl->previous; + removevars(fs, bl->nactvar); + lua_assert(bl->nactvar == fs->nactvar); + fs->freereg = fs->nactvar; /* free registers */ + ls->dyd->label.n = bl->firstlabel; /* remove local labels */ + if (bl->previous) /* inner block? */ + movegotosout(fs, bl); /* update pending gotos to outer block */ + else if (bl->firstgoto < ls->dyd->gt.n) /* pending gotos in outer block? */ + undefgoto(ls, &ls->dyd->gt.arr[bl->firstgoto]); /* error */ +} + + +/* +** adds a new prototype into list of prototypes +*/ +static Proto *addprototype (LexState *ls) { + Proto *clp; + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; /* prototype of current function */ + if (fs->np >= f->sizep) { + int oldsize = f->sizep; + luaM_growvector(L, f->p, fs->np, f->sizep, Proto *, MAXARG_Bx, "functions"); + while (oldsize < f->sizep) + f->p[oldsize++] = NULL; + } + f->p[fs->np++] = clp = luaF_newproto(L); + luaC_objbarrier(L, f, clp); + return clp; +} + + +/* +** codes instruction to create new closure in parent function. +** The OP_CLOSURE instruction must use the last available register, +** so that, if it invokes the GC, the GC knows which registers +** are in use at that time. +*/ +static void codeclosure (LexState *ls, expdesc *v) { + FuncState *fs = ls->fs->prev; + init_exp(v, VRELOCABLE, luaK_codeABx(fs, OP_CLOSURE, 0, fs->np - 1)); + luaK_exp2nextreg(fs, v); /* fix it at the last register */ +} + + +static void open_func (LexState *ls, FuncState *fs, BlockCnt *bl) { + Proto *f; + fs->prev = ls->fs; /* linked list of funcstates */ + fs->ls = ls; + ls->fs = fs; + fs->pc = 0; + fs->lasttarget = 0; + fs->jpc = NO_JUMP; + fs->freereg = 0; + fs->nk = 0; + fs->np = 0; + fs->nups = 0; + fs->nlocvars = 0; + fs->nactvar = 0; + fs->firstlocal = ls->dyd->actvar.n; + fs->bl = NULL; + f = fs->f; + f->source = ls->source; + luaC_objbarrier(ls->L, f, f->source); + f->maxstacksize = 2; /* registers 0/1 are always valid */ + enterblock(fs, bl, 0); +} + + +static void close_func (LexState *ls) { + lua_State *L = ls->L; + FuncState *fs = ls->fs; + Proto *f = fs->f; + luaK_ret(fs, 0, 0); /* final return */ + leaveblock(fs); + luaM_reallocvector(L, f->code, f->sizecode, fs->pc, Instruction); + f->sizecode = fs->pc; + luaM_reallocvector(L, f->lineinfo, f->sizelineinfo, fs->pc, int); + f->sizelineinfo = fs->pc; + luaM_reallocvector(L, f->k, f->sizek, fs->nk, TValue); + f->sizek = fs->nk; + luaM_reallocvector(L, f->p, f->sizep, fs->np, Proto *); + f->sizep = fs->np; + luaM_reallocvector(L, f->locvars, f->sizelocvars, fs->nlocvars, LocVar); + f->sizelocvars = fs->nlocvars; + luaM_reallocvector(L, f->upvalues, f->sizeupvalues, fs->nups, Upvaldesc); + f->sizeupvalues = fs->nups; + lua_assert(fs->bl == NULL); + ls->fs = fs->prev; + luaC_checkGC(L); +} + + + +/*============================================================*/ +/* GRAMMAR RULES */ +/*============================================================*/ + + +/* +** check whether current token is in the follow set of a block. +** 'until' closes syntactical blocks, but do not close scope, +** so it is handled in separate. +*/ +static int block_follow (LexState *ls, int withuntil) { + switch (ls->t.token) { + case TK_ELSE: case TK_ELSEIF: + case TK_END: case TK_EOS: + return 1; + case TK_UNTIL: return withuntil; + default: return 0; + } +} + + +static void statlist (LexState *ls) { + /* statlist -> { stat [';'] } */ + while (!block_follow(ls, 1)) { + if (ls->t.token == TK_RETURN) { + statement(ls); + return; /* 'return' must be last statement */ + } + statement(ls); + } +} + + +static void fieldsel (LexState *ls, expdesc *v) { + /* fieldsel -> ['.' | ':'] NAME */ + FuncState *fs = ls->fs; + expdesc key; + luaK_exp2anyregup(fs, v); + luaX_next(ls); /* skip the dot or colon */ + checkname(ls, &key); + luaK_indexed(fs, v, &key); +} + + +static void yindex (LexState *ls, expdesc *v) { + /* index -> '[' expr ']' */ + luaX_next(ls); /* skip the '[' */ + expr(ls, v); + luaK_exp2val(ls->fs, v); + checknext(ls, ']'); +} + + +/* +** {====================================================================== +** Rules for Constructors +** ======================================================================= +*/ + + +struct ConsControl { + expdesc v; /* last list item read */ + expdesc *t; /* table descriptor */ + int nh; /* total number of 'record' elements */ + int na; /* total number of array elements */ + int tostore; /* number of array elements pending to be stored */ +}; + + +static void recfield (LexState *ls, struct ConsControl *cc) { + /* recfield -> (NAME | '['exp1']') = exp1 */ + FuncState *fs = ls->fs; + int reg = ls->fs->freereg; + expdesc key, val; + int rkkey; + if (ls->t.token == TK_NAME) { + checklimit(fs, cc->nh, MAX_INT, "items in a constructor"); + checkname(ls, &key); + } + else /* ls->t.token == '[' */ + yindex(ls, &key); + cc->nh++; + checknext(ls, '='); + rkkey = luaK_exp2RK(fs, &key); + expr(ls, &val); + luaK_codeABC(fs, OP_SETTABLE, cc->t->u.info, rkkey, luaK_exp2RK(fs, &val)); + fs->freereg = reg; /* free registers */ +} + + +static void closelistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->v.k == VVOID) return; /* there is no list item */ + luaK_exp2nextreg(fs, &cc->v); + cc->v.k = VVOID; + if (cc->tostore == LFIELDS_PER_FLUSH) { + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); /* flush */ + cc->tostore = 0; /* no more items pending */ + } +} + + +static void lastlistfield (FuncState *fs, struct ConsControl *cc) { + if (cc->tostore == 0) return; + if (hasmultret(cc->v.k)) { + luaK_setmultret(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, LUA_MULTRET); + cc->na--; /* do not count last expression (unknown number of elements) */ + } + else { + if (cc->v.k != VVOID) + luaK_exp2nextreg(fs, &cc->v); + luaK_setlist(fs, cc->t->u.info, cc->na, cc->tostore); + } +} + + +static void listfield (LexState *ls, struct ConsControl *cc) { + /* listfield -> exp */ + expr(ls, &cc->v); + checklimit(ls->fs, cc->na, MAX_INT, "items in a constructor"); + cc->na++; + cc->tostore++; +} + + +static void field (LexState *ls, struct ConsControl *cc) { + /* field -> listfield | recfield */ + switch(ls->t.token) { + case TK_NAME: { /* may be 'listfield' or 'recfield' */ + if (luaX_lookahead(ls) != '=') /* expression? */ + listfield(ls, cc); + else + recfield(ls, cc); + break; + } + case '[': { + recfield(ls, cc); + break; + } + default: { + listfield(ls, cc); + break; + } + } +} + + +static void constructor (LexState *ls, expdesc *t) { + /* constructor -> '{' [ field { sep field } [sep] ] '}' + sep -> ',' | ';' */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + int pc = luaK_codeABC(fs, OP_NEWTABLE, 0, 0, 0); + struct ConsControl cc; + cc.na = cc.nh = cc.tostore = 0; + cc.t = t; + init_exp(t, VRELOCABLE, pc); + init_exp(&cc.v, VVOID, 0); /* no value (yet) */ + luaK_exp2nextreg(ls->fs, t); /* fix it at stack top */ + checknext(ls, '{'); + do { + lua_assert(cc.v.k == VVOID || cc.tostore > 0); + if (ls->t.token == '}') break; + closelistfield(fs, &cc); + field(ls, &cc); + } while (testnext(ls, ',') || testnext(ls, ';')); + check_match(ls, '}', '{', line); + lastlistfield(fs, &cc); + SETARG_B(fs->f->code[pc], luaO_int2fb(cc.na)); /* set initial array size */ + SETARG_C(fs->f->code[pc], luaO_int2fb(cc.nh)); /* set initial table size */ +} + +/* }====================================================================== */ + + + +static void parlist (LexState *ls) { + /* parlist -> [ param { ',' param } ] */ + FuncState *fs = ls->fs; + Proto *f = fs->f; + int nparams = 0; + f->is_vararg = 0; + if (ls->t.token != ')') { /* is 'parlist' not empty? */ + do { + switch (ls->t.token) { + case TK_NAME: { /* param -> NAME */ + new_localvar(ls, str_checkname(ls)); + nparams++; + break; + } + case TK_DOTS: { /* param -> '...' */ + luaX_next(ls); + f->is_vararg = 1; /* declared vararg */ + break; + } + default: luaX_syntaxerror(ls, " or '...' expected"); + } + } while (!f->is_vararg && testnext(ls, ',')); + } + adjustlocalvars(ls, nparams); + f->numparams = cast_byte(fs->nactvar); + luaK_reserveregs(fs, fs->nactvar); /* reserve register for parameters */ +} + + +static void body (LexState *ls, expdesc *e, int ismethod, int line) { + /* body -> '(' parlist ')' block END */ + FuncState new_fs; + BlockCnt bl; + new_fs.f = addprototype(ls); + new_fs.f->linedefined = line; + open_func(ls, &new_fs, &bl); + checknext(ls, '('); + if (ismethod) { + new_localvarliteral(ls, "self"); /* create 'self' parameter */ + adjustlocalvars(ls, 1); + } + parlist(ls); + checknext(ls, ')'); + statlist(ls); + new_fs.f->lastlinedefined = ls->linenumber; + check_match(ls, TK_END, TK_FUNCTION, line); + codeclosure(ls, e); + close_func(ls); +} + + +static int explist (LexState *ls, expdesc *v) { + /* explist -> expr { ',' expr } */ + int n = 1; /* at least one expression */ + expr(ls, v); + while (testnext(ls, ',')) { + luaK_exp2nextreg(ls->fs, v); + expr(ls, v); + n++; + } + return n; +} + + +static void funcargs (LexState *ls, expdesc *f, int line) { + FuncState *fs = ls->fs; + expdesc args; + int base, nparams; + switch (ls->t.token) { + case '(': { /* funcargs -> '(' [ explist ] ')' */ + luaX_next(ls); + if (ls->t.token == ')') /* arg list is empty? */ + args.k = VVOID; + else { + explist(ls, &args); + luaK_setmultret(fs, &args); + } + check_match(ls, ')', '(', line); + break; + } + case '{': { /* funcargs -> constructor */ + constructor(ls, &args); + break; + } + case TK_STRING: { /* funcargs -> STRING */ + codestring(ls, &args, ls->t.seminfo.ts); + luaX_next(ls); /* must use 'seminfo' before 'next' */ + break; + } + default: { + luaX_syntaxerror(ls, "function arguments expected"); + } + } + lua_assert(f->k == VNONRELOC); + base = f->u.info; /* base register for call */ + if (hasmultret(args.k)) + nparams = LUA_MULTRET; /* open call */ + else { + if (args.k != VVOID) + luaK_exp2nextreg(fs, &args); /* close last argument */ + nparams = fs->freereg - (base+1); + } + init_exp(f, VCALL, luaK_codeABC(fs, OP_CALL, base, nparams+1, 2)); + luaK_fixline(fs, line); + fs->freereg = base+1; /* call remove function and arguments and leaves + (unless changed) one result */ +} + + + + +/* +** {====================================================================== +** Expression parsing +** ======================================================================= +*/ + + +static void primaryexp (LexState *ls, expdesc *v) { + /* primaryexp -> NAME | '(' expr ')' */ + switch (ls->t.token) { + case '(': { + int line = ls->linenumber; + luaX_next(ls); + expr(ls, v); + check_match(ls, ')', '(', line); + luaK_dischargevars(ls->fs, v); + return; + } + case TK_NAME: { + singlevar(ls, v); + return; + } + default: { + luaX_syntaxerror(ls, "unexpected symbol"); + } + } +} + + +static void suffixedexp (LexState *ls, expdesc *v) { + /* suffixedexp -> + primaryexp { '.' NAME | '[' exp ']' | ':' NAME funcargs | funcargs } */ + FuncState *fs = ls->fs; + int line = ls->linenumber; + primaryexp(ls, v); + for (;;) { + switch (ls->t.token) { + case '.': { /* fieldsel */ + fieldsel(ls, v); + break; + } + case '[': { /* '[' exp1 ']' */ + expdesc key; + luaK_exp2anyregup(fs, v); + yindex(ls, &key); + luaK_indexed(fs, v, &key); + break; + } + case ':': { /* ':' NAME funcargs */ + expdesc key; + luaX_next(ls); + checkname(ls, &key); + luaK_self(fs, v, &key); + funcargs(ls, v, line); + break; + } + case '(': case TK_STRING: case '{': { /* funcargs */ + luaK_exp2nextreg(fs, v); + funcargs(ls, v, line); + break; + } + default: return; + } + } +} + + +static void simpleexp (LexState *ls, expdesc *v) { + /* simpleexp -> FLT | INT | STRING | NIL | TRUE | FALSE | ... | + constructor | FUNCTION body | suffixedexp */ + switch (ls->t.token) { + case TK_FLT: { + init_exp(v, VKFLT, 0); + v->u.nval = ls->t.seminfo.r; + break; + } + case TK_INT: { + init_exp(v, VKINT, 0); + v->u.ival = ls->t.seminfo.i; + break; + } + case TK_STRING: { + codestring(ls, v, ls->t.seminfo.ts); + break; + } + case TK_NIL: { + init_exp(v, VNIL, 0); + break; + } + case TK_TRUE: { + init_exp(v, VTRUE, 0); + break; + } + case TK_FALSE: { + init_exp(v, VFALSE, 0); + break; + } + case TK_DOTS: { /* vararg */ + FuncState *fs = ls->fs; + check_condition(ls, fs->f->is_vararg, + "cannot use '...' outside a vararg function"); + init_exp(v, VVARARG, luaK_codeABC(fs, OP_VARARG, 0, 1, 0)); + break; + } + case '{': { /* constructor */ + constructor(ls, v); + return; + } + case TK_FUNCTION: { + luaX_next(ls); + body(ls, v, 0, ls->linenumber); + return; + } + default: { + suffixedexp(ls, v); + return; + } + } + luaX_next(ls); +} + + +static UnOpr getunopr (int op) { + switch (op) { + case TK_NOT: return OPR_NOT; + case '-': return OPR_MINUS; + case '~': return OPR_BNOT; + case '#': return OPR_LEN; + default: return OPR_NOUNOPR; + } +} + + +static BinOpr getbinopr (int op) { + switch (op) { + case '+': return OPR_ADD; + case '-': return OPR_SUB; + case '*': return OPR_MUL; + case '%': return OPR_MOD; + case '^': return OPR_POW; + case '/': return OPR_DIV; + case TK_IDIV: return OPR_IDIV; + case '&': return OPR_BAND; + case '|': return OPR_BOR; + case '~': return OPR_BXOR; + case TK_SHL: return OPR_SHL; + case TK_SHR: return OPR_SHR; + case TK_CONCAT: return OPR_CONCAT; + case TK_NE: return OPR_NE; + case TK_EQ: return OPR_EQ; + case '<': return OPR_LT; + case TK_LE: return OPR_LE; + case '>': return OPR_GT; + case TK_GE: return OPR_GE; + case TK_AND: return OPR_AND; + case TK_OR: return OPR_OR; + default: return OPR_NOBINOPR; + } +} + + +static const struct { + lu_byte left; /* left priority for each binary operator */ + lu_byte right; /* right priority */ +} priority[] = { /* ORDER OPR */ + {10, 10}, {10, 10}, /* '+' '-' */ + {11, 11}, {11, 11}, /* '*' '%' */ + {14, 13}, /* '^' (right associative) */ + {11, 11}, {11, 11}, /* '/' '//' */ + {6, 6}, {4, 4}, {5, 5}, /* '&' '|' '~' */ + {7, 7}, {7, 7}, /* '<<' '>>' */ + {9, 8}, /* '..' (right associative) */ + {3, 3}, {3, 3}, {3, 3}, /* ==, <, <= */ + {3, 3}, {3, 3}, {3, 3}, /* ~=, >, >= */ + {2, 2}, {1, 1} /* and, or */ +}; + +#define UNARY_PRIORITY 12 /* priority for unary operators */ + + +/* +** subexpr -> (simpleexp | unop subexpr) { binop subexpr } +** where 'binop' is any binary operator with a priority higher than 'limit' +*/ +static BinOpr subexpr (LexState *ls, expdesc *v, int limit) { + BinOpr op; + UnOpr uop; + enterlevel(ls); + uop = getunopr(ls->t.token); + if (uop != OPR_NOUNOPR) { + int line = ls->linenumber; + luaX_next(ls); + subexpr(ls, v, UNARY_PRIORITY); + luaK_prefix(ls->fs, uop, v, line); + } + else simpleexp(ls, v); + /* expand while operators have priorities higher than 'limit' */ + op = getbinopr(ls->t.token); + while (op != OPR_NOBINOPR && priority[op].left > limit) { + expdesc v2; + BinOpr nextop; + int line = ls->linenumber; + luaX_next(ls); + luaK_infix(ls->fs, op, v); + /* read sub-expression with higher priority */ + nextop = subexpr(ls, &v2, priority[op].right); + luaK_posfix(ls->fs, op, v, &v2, line); + op = nextop; + } + leavelevel(ls); + return op; /* return first untreated operator */ +} + + +static void expr (LexState *ls, expdesc *v) { + subexpr(ls, v, 0); +} + +/* }==================================================================== */ + + + +/* +** {====================================================================== +** Rules for Statements +** ======================================================================= +*/ + + +static void block (LexState *ls) { + /* block -> statlist */ + FuncState *fs = ls->fs; + BlockCnt bl; + enterblock(fs, &bl, 0); + statlist(ls); + leaveblock(fs); +} + + +/* +** structure to chain all variables in the left-hand side of an +** assignment +*/ +struct LHS_assign { + struct LHS_assign *prev; + expdesc v; /* variable (global, local, upvalue, or indexed) */ +}; + + +/* +** check whether, in an assignment to an upvalue/local variable, the +** upvalue/local variable is begin used in a previous assignment to a +** table. If so, save original upvalue/local value in a safe place and +** use this safe copy in the previous assignment. +*/ +static void check_conflict (LexState *ls, struct LHS_assign *lh, expdesc *v) { + FuncState *fs = ls->fs; + int extra = fs->freereg; /* eventual position to save local variable */ + int conflict = 0; + for (; lh; lh = lh->prev) { /* check all previous assignments */ + if (lh->v.k == VINDEXED) { /* assigning to a table? */ + /* table is the upvalue/local being assigned now? */ + if (lh->v.u.ind.vt == v->k && lh->v.u.ind.t == v->u.info) { + conflict = 1; + lh->v.u.ind.vt = VLOCAL; + lh->v.u.ind.t = extra; /* previous assignment will use safe copy */ + } + /* index is the local being assigned? (index cannot be upvalue) */ + if (v->k == VLOCAL && lh->v.u.ind.idx == v->u.info) { + conflict = 1; + lh->v.u.ind.idx = extra; /* previous assignment will use safe copy */ + } + } + } + if (conflict) { + /* copy upvalue/local value to a temporary (in position 'extra') */ + OpCode op = (v->k == VLOCAL) ? OP_MOVE : OP_GETUPVAL; + luaK_codeABC(fs, op, extra, v->u.info, 0); + luaK_reserveregs(fs, 1); + } +} + + +static void assignment (LexState *ls, struct LHS_assign *lh, int nvars) { + expdesc e; + check_condition(ls, vkisvar(lh->v.k), "syntax error"); + if (testnext(ls, ',')) { /* assignment -> ',' suffixedexp assignment */ + struct LHS_assign nv; + nv.prev = lh; + suffixedexp(ls, &nv.v); + if (nv.v.k != VINDEXED) + check_conflict(ls, lh, &nv.v); + checklimit(ls->fs, nvars + ls->L->nCcalls, LUAI_MAXCCALLS, + "C levels"); + assignment(ls, &nv, nvars+1); + } + else { /* assignment -> '=' explist */ + int nexps; + checknext(ls, '='); + nexps = explist(ls, &e); + if (nexps != nvars) + adjust_assign(ls, nvars, nexps, &e); + else { + luaK_setoneret(ls->fs, &e); /* close last expression */ + luaK_storevar(ls->fs, &lh->v, &e); + return; /* avoid default */ + } + } + init_exp(&e, VNONRELOC, ls->fs->freereg-1); /* default assignment */ + luaK_storevar(ls->fs, &lh->v, &e); +} + + +static int cond (LexState *ls) { + /* cond -> exp */ + expdesc v; + expr(ls, &v); /* read condition */ + if (v.k == VNIL) v.k = VFALSE; /* 'falses' are all equal here */ + luaK_goiftrue(ls->fs, &v); + return v.f; +} + + +static void gotostat (LexState *ls, int pc) { + int line = ls->linenumber; + TString *label; + int g; + if (testnext(ls, TK_GOTO)) + label = str_checkname(ls); + else { + luaX_next(ls); /* skip break */ + label = luaS_new(ls->L, "break"); + } + g = newlabelentry(ls, &ls->dyd->gt, label, line, pc); + findlabel(ls, g); /* close it if label already defined */ +} + + +/* check for repeated labels on the same block */ +static void checkrepeated (FuncState *fs, Labellist *ll, TString *label) { + int i; + for (i = fs->bl->firstlabel; i < ll->n; i++) { + if (eqstr(label, ll->arr[i].name)) { + const char *msg = luaO_pushfstring(fs->ls->L, + "label '%s' already defined on line %d", + getstr(label), ll->arr[i].line); + semerror(fs->ls, msg); + } + } +} + + +/* skip no-op statements */ +static void skipnoopstat (LexState *ls) { + while (ls->t.token == ';' || ls->t.token == TK_DBCOLON) + statement(ls); +} + + +static void labelstat (LexState *ls, TString *label, int line) { + /* label -> '::' NAME '::' */ + FuncState *fs = ls->fs; + Labellist *ll = &ls->dyd->label; + int l; /* index of new label being created */ + checkrepeated(fs, ll, label); /* check for repeated labels */ + checknext(ls, TK_DBCOLON); /* skip double colon */ + /* create new entry for this label */ + l = newlabelentry(ls, ll, label, line, luaK_getlabel(fs)); + skipnoopstat(ls); /* skip other no-op statements */ + if (block_follow(ls, 0)) { /* label is last no-op statement in the block? */ + /* assume that locals are already out of scope */ + ll->arr[l].nactvar = fs->bl->nactvar; + } + findgotos(ls, &ll->arr[l]); +} + + +static void whilestat (LexState *ls, int line) { + /* whilestat -> WHILE cond DO block END */ + FuncState *fs = ls->fs; + int whileinit; + int condexit; + BlockCnt bl; + luaX_next(ls); /* skip WHILE */ + whileinit = luaK_getlabel(fs); + condexit = cond(ls); + enterblock(fs, &bl, 1); + checknext(ls, TK_DO); + block(ls); + luaK_jumpto(fs, whileinit); + check_match(ls, TK_END, TK_WHILE, line); + leaveblock(fs); + luaK_patchtohere(fs, condexit); /* false conditions finish the loop */ +} + + +static void repeatstat (LexState *ls, int line) { + /* repeatstat -> REPEAT block UNTIL cond */ + int condexit; + FuncState *fs = ls->fs; + int repeat_init = luaK_getlabel(fs); + BlockCnt bl1, bl2; + enterblock(fs, &bl1, 1); /* loop block */ + enterblock(fs, &bl2, 0); /* scope block */ + luaX_next(ls); /* skip REPEAT */ + statlist(ls); + check_match(ls, TK_UNTIL, TK_REPEAT, line); + condexit = cond(ls); /* read condition (inside scope block) */ + if (bl2.upval) /* upvalues? */ + luaK_patchclose(fs, condexit, bl2.nactvar); + leaveblock(fs); /* finish scope */ + luaK_patchlist(fs, condexit, repeat_init); /* close the loop */ + leaveblock(fs); /* finish loop */ +} + + +static int exp1 (LexState *ls) { + expdesc e; + int reg; + expr(ls, &e); + luaK_exp2nextreg(ls->fs, &e); + lua_assert(e.k == VNONRELOC); + reg = e.u.info; + return reg; +} + + +static void forbody (LexState *ls, int base, int line, int nvars, int isnum) { + /* forbody -> DO block */ + BlockCnt bl; + FuncState *fs = ls->fs; + int prep, endfor; + adjustlocalvars(ls, 3); /* control variables */ + checknext(ls, TK_DO); + prep = isnum ? luaK_codeAsBx(fs, OP_FORPREP, base, NO_JUMP) : luaK_jump(fs); + enterblock(fs, &bl, 0); /* scope for declared variables */ + adjustlocalvars(ls, nvars); + luaK_reserveregs(fs, nvars); + block(ls); + leaveblock(fs); /* end of scope for declared variables */ + luaK_patchtohere(fs, prep); + if (isnum) /* numeric for? */ + endfor = luaK_codeAsBx(fs, OP_FORLOOP, base, NO_JUMP); + else { /* generic for */ + luaK_codeABC(fs, OP_TFORCALL, base, 0, nvars); + luaK_fixline(fs, line); + endfor = luaK_codeAsBx(fs, OP_TFORLOOP, base + 2, NO_JUMP); + } + luaK_patchlist(fs, endfor, prep + 1); + luaK_fixline(fs, line); +} + + +static void fornum (LexState *ls, TString *varname, int line) { + /* fornum -> NAME = exp1,exp1[,exp1] forbody */ + FuncState *fs = ls->fs; + int base = fs->freereg; + new_localvarliteral(ls, "(for index)"); + new_localvarliteral(ls, "(for limit)"); + new_localvarliteral(ls, "(for step)"); + new_localvar(ls, varname); + checknext(ls, '='); + exp1(ls); /* initial value */ + checknext(ls, ','); + exp1(ls); /* limit */ + if (testnext(ls, ',')) + exp1(ls); /* optional step */ + else { /* default step = 1 */ + luaK_codek(fs, fs->freereg, luaK_intK(fs, 1)); + luaK_reserveregs(fs, 1); + } + forbody(ls, base, line, 1, 1); +} + + +static void forlist (LexState *ls, TString *indexname) { + /* forlist -> NAME {,NAME} IN explist forbody */ + FuncState *fs = ls->fs; + expdesc e; + int nvars = 4; /* gen, state, control, plus at least one declared var */ + int line; + int base = fs->freereg; + /* create control variables */ + new_localvarliteral(ls, "(for generator)"); + new_localvarliteral(ls, "(for state)"); + new_localvarliteral(ls, "(for control)"); + /* create declared variables */ + new_localvar(ls, indexname); + while (testnext(ls, ',')) { + new_localvar(ls, str_checkname(ls)); + nvars++; + } + checknext(ls, TK_IN); + line = ls->linenumber; + adjust_assign(ls, 3, explist(ls, &e), &e); + luaK_checkstack(fs, 3); /* extra space to call generator */ + forbody(ls, base, line, nvars - 3, 0); +} + + +static void forstat (LexState *ls, int line) { + /* forstat -> FOR (fornum | forlist) END */ + FuncState *fs = ls->fs; + TString *varname; + BlockCnt bl; + enterblock(fs, &bl, 1); /* scope for loop and control variables */ + luaX_next(ls); /* skip 'for' */ + varname = str_checkname(ls); /* first variable name */ + switch (ls->t.token) { + case '=': fornum(ls, varname, line); break; + case ',': case TK_IN: forlist(ls, varname); break; + default: luaX_syntaxerror(ls, "'=' or 'in' expected"); + } + check_match(ls, TK_END, TK_FOR, line); + leaveblock(fs); /* loop scope ('break' jumps to this point) */ +} + + +static void test_then_block (LexState *ls, int *escapelist) { + /* test_then_block -> [IF | ELSEIF] cond THEN block */ + BlockCnt bl; + FuncState *fs = ls->fs; + expdesc v; + int jf; /* instruction to skip 'then' code (if condition is false) */ + luaX_next(ls); /* skip IF or ELSEIF */ + expr(ls, &v); /* read condition */ + checknext(ls, TK_THEN); + if (ls->t.token == TK_GOTO || ls->t.token == TK_BREAK) { + luaK_goiffalse(ls->fs, &v); /* will jump to label if condition is true */ + enterblock(fs, &bl, 0); /* must enter block before 'goto' */ + gotostat(ls, v.t); /* handle goto/break */ + while (testnext(ls, ';')) {} /* skip colons */ + if (block_follow(ls, 0)) { /* 'goto' is the entire block? */ + leaveblock(fs); + return; /* and that is it */ + } + else /* must skip over 'then' part if condition is false */ + jf = luaK_jump(fs); + } + else { /* regular case (not goto/break) */ + luaK_goiftrue(ls->fs, &v); /* skip over block if condition is false */ + enterblock(fs, &bl, 0); + jf = v.f; + } + statlist(ls); /* 'then' part */ + leaveblock(fs); + if (ls->t.token == TK_ELSE || + ls->t.token == TK_ELSEIF) /* followed by 'else'/'elseif'? */ + luaK_concat(fs, escapelist, luaK_jump(fs)); /* must jump over it */ + luaK_patchtohere(fs, jf); +} + + +static void ifstat (LexState *ls, int line) { + /* ifstat -> IF cond THEN block {ELSEIF cond THEN block} [ELSE block] END */ + FuncState *fs = ls->fs; + int escapelist = NO_JUMP; /* exit list for finished parts */ + test_then_block(ls, &escapelist); /* IF cond THEN block */ + while (ls->t.token == TK_ELSEIF) + test_then_block(ls, &escapelist); /* ELSEIF cond THEN block */ + if (testnext(ls, TK_ELSE)) + block(ls); /* 'else' part */ + check_match(ls, TK_END, TK_IF, line); + luaK_patchtohere(fs, escapelist); /* patch escape list to 'if' end */ +} + + +static void localfunc (LexState *ls) { + expdesc b; + FuncState *fs = ls->fs; + new_localvar(ls, str_checkname(ls)); /* new local variable */ + adjustlocalvars(ls, 1); /* enter its scope */ + body(ls, &b, 0, ls->linenumber); /* function created in next register */ + /* debug information will only see the variable after this point! */ + getlocvar(fs, b.u.info)->startpc = fs->pc; +} + + +static void localstat (LexState *ls) { + /* stat -> LOCAL NAME {',' NAME} ['=' explist] */ + int nvars = 0; + int nexps; + expdesc e; + do { + new_localvar(ls, str_checkname(ls)); + nvars++; + } while (testnext(ls, ',')); + if (testnext(ls, '=')) + nexps = explist(ls, &e); + else { + e.k = VVOID; + nexps = 0; + } + adjust_assign(ls, nvars, nexps, &e); + adjustlocalvars(ls, nvars); +} + + +static int funcname (LexState *ls, expdesc *v) { + /* funcname -> NAME {fieldsel} [':' NAME] */ + int ismethod = 0; + singlevar(ls, v); + while (ls->t.token == '.') + fieldsel(ls, v); + if (ls->t.token == ':') { + ismethod = 1; + fieldsel(ls, v); + } + return ismethod; +} + + +static void funcstat (LexState *ls, int line) { + /* funcstat -> FUNCTION funcname body */ + int ismethod; + expdesc v, b; + luaX_next(ls); /* skip FUNCTION */ + ismethod = funcname(ls, &v); + body(ls, &b, ismethod, line); + luaK_storevar(ls->fs, &v, &b); + luaK_fixline(ls->fs, line); /* definition "happens" in the first line */ +} + + +static void exprstat (LexState *ls) { + /* stat -> func | assignment */ + FuncState *fs = ls->fs; + struct LHS_assign v; + suffixedexp(ls, &v.v); + if (ls->t.token == '=' || ls->t.token == ',') { /* stat -> assignment ? */ + v.prev = NULL; + assignment(ls, &v, 1); + } + else { /* stat -> func */ + check_condition(ls, v.v.k == VCALL, "syntax error"); + SETARG_C(getinstruction(fs, &v.v), 1); /* call statement uses no results */ + } +} + + +static void retstat (LexState *ls) { + /* stat -> RETURN [explist] [';'] */ + FuncState *fs = ls->fs; + expdesc e; + int first, nret; /* registers with returned values */ + if (block_follow(ls, 1) || ls->t.token == ';') + first = nret = 0; /* return no values */ + else { + nret = explist(ls, &e); /* optional return values */ + if (hasmultret(e.k)) { + luaK_setmultret(fs, &e); + if (e.k == VCALL && nret == 1) { /* tail call? */ + SET_OPCODE(getinstruction(fs,&e), OP_TAILCALL); + lua_assert(GETARG_A(getinstruction(fs,&e)) == fs->nactvar); + } + first = fs->nactvar; + nret = LUA_MULTRET; /* return all values */ + } + else { + if (nret == 1) /* only one single value? */ + first = luaK_exp2anyreg(fs, &e); + else { + luaK_exp2nextreg(fs, &e); /* values must go to the stack */ + first = fs->nactvar; /* return all active values */ + lua_assert(nret == fs->freereg - first); + } + } + } + luaK_ret(fs, first, nret); + testnext(ls, ';'); /* skip optional semicolon */ +} + + +static void statement (LexState *ls) { + int line = ls->linenumber; /* may be needed for error messages */ + enterlevel(ls); + switch (ls->t.token) { + case ';': { /* stat -> ';' (empty statement) */ + luaX_next(ls); /* skip ';' */ + break; + } + case TK_IF: { /* stat -> ifstat */ + ifstat(ls, line); + break; + } + case TK_WHILE: { /* stat -> whilestat */ + whilestat(ls, line); + break; + } + case TK_DO: { /* stat -> DO block END */ + luaX_next(ls); /* skip DO */ + block(ls); + check_match(ls, TK_END, TK_DO, line); + break; + } + case TK_FOR: { /* stat -> forstat */ + forstat(ls, line); + break; + } + case TK_REPEAT: { /* stat -> repeatstat */ + repeatstat(ls, line); + break; + } + case TK_FUNCTION: { /* stat -> funcstat */ + funcstat(ls, line); + break; + } + case TK_LOCAL: { /* stat -> localstat */ + luaX_next(ls); /* skip LOCAL */ + if (testnext(ls, TK_FUNCTION)) /* local function? */ + localfunc(ls); + else + localstat(ls); + break; + } + case TK_DBCOLON: { /* stat -> label */ + luaX_next(ls); /* skip double colon */ + labelstat(ls, str_checkname(ls), line); + break; + } + case TK_RETURN: { /* stat -> retstat */ + luaX_next(ls); /* skip RETURN */ + retstat(ls); + break; + } + case TK_BREAK: /* stat -> breakstat */ + case TK_GOTO: { /* stat -> 'goto' NAME */ + gotostat(ls, luaK_jump(ls->fs)); + break; + } + default: { /* stat -> func | assignment */ + exprstat(ls); + break; + } + } + lua_assert(ls->fs->f->maxstacksize >= ls->fs->freereg && + ls->fs->freereg >= ls->fs->nactvar); + ls->fs->freereg = ls->fs->nactvar; /* free registers */ + leavelevel(ls); +} + +/* }====================================================================== */ + + +/* +** compiles the main function, which is a regular vararg function with an +** upvalue named LUA_ENV +*/ +static void mainfunc (LexState *ls, FuncState *fs) { + BlockCnt bl; + expdesc v; + open_func(ls, fs, &bl); + fs->f->is_vararg = 1; /* main function is always declared vararg */ + init_exp(&v, VLOCAL, 0); /* create and... */ + newupvalue(fs, ls->envn, &v); /* ...set environment upvalue */ + luaC_objbarrier(ls->L, fs->f, ls->envn); + luaX_next(ls); /* read first token */ + statlist(ls); /* parse main body */ + check(ls, TK_EOS); + close_func(ls); +} + + +LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar) { + LexState lexstate; + FuncState funcstate; + LClosure *cl = luaF_newLclosure(L, 1); /* create main closure */ + setclLvalue(L, L->top, cl); /* anchor it (to avoid being collected) */ + luaD_inctop(L); + lexstate.h = luaH_new(L); /* create table for scanner */ + sethvalue(L, L->top, lexstate.h); /* anchor it */ + luaD_inctop(L); + funcstate.f = cl->p = luaF_newproto(L); + luaC_objbarrier(L, cl, cl->p); + funcstate.f->source = luaS_new(L, name); /* create and anchor TString */ + lua_assert(iswhite(funcstate.f)); /* do not need barrier here */ + lexstate.buff = buff; + lexstate.dyd = dyd; + dyd->actvar.n = dyd->gt.n = dyd->label.n = 0; + luaX_setinput(L, &lexstate, z, funcstate.f->source, firstchar); + mainfunc(&lexstate, &funcstate); + lua_assert(!funcstate.prev && funcstate.nups == 1 && !lexstate.fs); + /* all scopes should be correctly finished */ + lua_assert(dyd->actvar.n == 0 && dyd->gt.n == 0 && dyd->label.n == 0); + L->top--; /* remove scanner's table */ + return cl; /* closure is on the stack, too */ +} + diff --git a/src/lua/lparser.h b/src/lua/lparser.h new file mode 100644 index 000000000000..f45b23cba56b --- /dev/null +++ b/src/lua/lparser.h @@ -0,0 +1,133 @@ +/* +** $Id: lparser.h,v 1.76.1.1 2017/04/19 17:20:42 roberto Exp $ +** Lua Parser +** See Copyright Notice in lua.h +*/ + +#ifndef lparser_h +#define lparser_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* +** Expression and variable descriptor. +** Code generation for variables and expressions can be delayed to allow +** optimizations; An 'expdesc' structure describes a potentially-delayed +** variable/expression. It has a description of its "main" value plus a +** list of conditional jumps that can also produce its value (generated +** by short-circuit operators 'and'/'or'). +*/ + +/* kinds of variables/expressions */ +typedef enum { + VVOID, /* when 'expdesc' describes the last expression a list, + this kind means an empty list (so, no expression) */ + VNIL, /* constant nil */ + VTRUE, /* constant true */ + VFALSE, /* constant false */ + VK, /* constant in 'k'; info = index of constant in 'k' */ + VKFLT, /* floating constant; nval = numerical float value */ + VKINT, /* integer constant; nval = numerical integer value */ + VNONRELOC, /* expression has its value in a fixed register; + info = result register */ + VLOCAL, /* local variable; info = local register */ + VUPVAL, /* upvalue variable; info = index of upvalue in 'upvalues' */ + VINDEXED, /* indexed variable; + ind.vt = whether 't' is register or upvalue; + ind.t = table register or upvalue; + ind.idx = key's R/K index */ + VJMP, /* expression is a test/comparison; + info = pc of corresponding jump instruction */ + VRELOCABLE, /* expression can put result in any register; + info = instruction pc */ + VCALL, /* expression is a function call; info = instruction pc */ + VVARARG /* vararg expression; info = instruction pc */ +} expkind; + + +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) + +typedef struct expdesc { + expkind k; + union { + lua_Integer ival; /* for VKINT */ + lua_Number nval; /* for VKFLT */ + int info; /* for generic use */ + struct { /* for indexed variables (VINDEXED) */ + short idx; /* index (R/K) */ + lu_byte t; /* table (register or upvalue) */ + lu_byte vt; /* whether 't' is register (VLOCAL) or upvalue (VUPVAL) */ + } ind; + } u; + int t; /* patch list of 'exit when true' */ + int f; /* patch list of 'exit when false' */ +} expdesc; + + +/* description of active local variable */ +typedef struct Vardesc { + short idx; /* variable index in stack */ +} Vardesc; + + +/* description of pending goto statements and label statements */ +typedef struct Labeldesc { + TString *name; /* label identifier */ + int pc; /* position in code */ + int line; /* line where it appeared */ + lu_byte nactvar; /* local level where it appears in current block */ +} Labeldesc; + + +/* list of labels or gotos */ +typedef struct Labellist { + Labeldesc *arr; /* array */ + int n; /* number of entries in use */ + int size; /* array size */ +} Labellist; + + +/* dynamic structures used by the parser */ +typedef struct Dyndata { + struct { /* list of active local variables */ + Vardesc *arr; + int n; + int size; + } actvar; + Labellist gt; /* list of pending gotos */ + Labellist label; /* list of active labels */ +} Dyndata; + + +/* control of blocks */ +struct BlockCnt; /* defined in lparser.c */ + + +/* state needed to generate code for a given function */ +typedef struct FuncState { + Proto *f; /* current function header */ + struct FuncState *prev; /* enclosing function */ + struct LexState *ls; /* lexical state */ + struct BlockCnt *bl; /* chain of current blocks */ + int pc; /* next position to code (equivalent to 'ncode') */ + int lasttarget; /* 'label' of last 'jump label' */ + int jpc; /* list of pending jumps to 'pc' */ + int nk; /* number of elements in 'k' */ + int np; /* number of elements in 'p' */ + int firstlocal; /* index of first local var (in Dyndata array) */ + short nlocvars; /* number of elements in 'f->locvars' */ + lu_byte nactvar; /* number of active local variables */ + lu_byte nups; /* number of upvalues */ + lu_byte freereg; /* first free register */ +} FuncState; + + +LUAI_FUNC LClosure *luaY_parser (lua_State *L, ZIO *z, Mbuffer *buff, + Dyndata *dyd, const char *name, int firstchar); + + +#endif diff --git a/src/lua/lprefix.h b/src/lua/lprefix.h new file mode 100644 index 000000000000..9a749a3f30cc --- /dev/null +++ b/src/lua/lprefix.h @@ -0,0 +1,45 @@ +/* +** $Id: lprefix.h,v 1.2.1.1 2017/04/19 17:20:42 roberto Exp $ +** Definitions for Lua code that must come before any other header file +** See Copyright Notice in lua.h +*/ + +#ifndef lprefix_h +#define lprefix_h + + +/* +** Allows POSIX/XSI stuff +*/ +#if !defined(LUA_USE_C89) /* { */ + +#if !defined(_XOPEN_SOURCE) +#define _XOPEN_SOURCE 600 +#elif _XOPEN_SOURCE == 0 +#undef _XOPEN_SOURCE /* use -D_XOPEN_SOURCE=0 to undefine it */ +#endif + +/* +** Allows manipulation of large files in gcc and some other compilers +*/ +#if !defined(LUA_32BITS) && !defined(_FILE_OFFSET_BITS) +#define _LARGEFILE_SOURCE 1 +#define _FILE_OFFSET_BITS 64 +#endif + +#endif /* } */ + + +/* +** Windows stuff +*/ +#if defined(_WIN32) /* { */ + +#if !defined(_CRT_SECURE_NO_WARNINGS) +#define _CRT_SECURE_NO_WARNINGS /* avoid warnings about ISO C functions */ +#endif + +#endif /* } */ + +#endif + diff --git a/src/lua/lstate.c b/src/lua/lstate.c new file mode 100644 index 000000000000..c1a76643c337 --- /dev/null +++ b/src/lua/lstate.c @@ -0,0 +1,347 @@ +/* +** $Id: lstate.c,v 2.133.1.1 2017/04/19 17:39:34 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#define lstate_c +#define LUA_CORE + +#include "lprefix.h" + + +#include +#include + +#include "lua.h" + +#include "lapi.h" +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "llex.h" +#include "lmem.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" + + +#if !defined(LUAI_GCPAUSE) +#define LUAI_GCPAUSE 200 /* 200% */ +#endif + +#if !defined(LUAI_GCMUL) +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ +#endif + + +/* +** a macro to help the creation of a unique random seed when a state is +** created; the seed is used to randomize hashes. +*/ +#if !defined(luai_makeseed) +#include +#define luai_makeseed() cast(unsigned int, time(NULL)) +#endif + + + +/* +** thread state + extra space +*/ +typedef struct LX { + lu_byte extra_[LUA_EXTRASPACE]; + lua_State l; +} LX; + + +/* +** Main thread combines a thread state and the global state +*/ +typedef struct LG { + LX l; + global_State g; +} LG; + + + +#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) + + +/* +** Compute an initial seed as random as possible. Rely on Address Space +** Layout Randomization (if present) to increase randomness.. +*/ +#define addbuff(b,p,e) \ + { size_t t = cast(size_t, e); \ + memcpy(b + p, &t, sizeof(t)); p += sizeof(t); } + +static unsigned int makeseed (lua_State *L) { + char buff[4 * sizeof(size_t)]; + unsigned int h = luai_makeseed(); + int p = 0; + addbuff(buff, p, L); /* heap variable */ + addbuff(buff, p, &h); /* local variable */ + addbuff(buff, p, luaO_nilobject); /* global variable */ + addbuff(buff, p, &lua_newstate); /* public function */ + lua_assert(p == sizeof(buff)); + return luaS_hash(buff, p, h); +} + + +/* +** set GCdebt to a new value keeping the value (totalbytes + GCdebt) +** invariant (and avoiding underflows in 'totalbytes') +*/ +void luaE_setdebt (global_State *g, l_mem debt) { + l_mem tb = gettotalbytes(g); + lua_assert(tb > 0); + if (debt < tb - MAX_LMEM) + debt = tb - MAX_LMEM; /* will make 'totalbytes == MAX_LMEM' */ + g->totalbytes = tb - debt; + g->GCdebt = debt; +} + + +CallInfo *luaE_extendCI (lua_State *L) { + CallInfo *ci = luaM_new(L, CallInfo); + lua_assert(L->ci->next == NULL); + L->ci->next = ci; + ci->previous = L->ci; + ci->next = NULL; + L->nci++; + return ci; +} + + +/* +** free all CallInfo structures not in use by a thread +*/ +void luaE_freeCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next = ci->next; + ci->next = NULL; + while ((ci = next) != NULL) { + next = ci->next; + luaM_free(L, ci); + L->nci--; + } +} + + +/* +** free half of the CallInfo structures not in use by a thread +*/ +void luaE_shrinkCI (lua_State *L) { + CallInfo *ci = L->ci; + CallInfo *next2; /* next's next */ + /* while there are two nexts */ + while (ci->next != NULL && (next2 = ci->next->next) != NULL) { + luaM_free(L, ci->next); /* free next */ + L->nci--; + ci->next = next2; /* remove 'next' from the list */ + next2->previous = ci; + ci = next2; /* keep next's next */ + } +} + + +static void stack_init (lua_State *L1, lua_State *L) { + int i; CallInfo *ci; + /* initialize stack array */ + L1->stack = luaM_newvector(L, BASIC_STACK_SIZE, TValue); + L1->stacksize = BASIC_STACK_SIZE; + for (i = 0; i < BASIC_STACK_SIZE; i++) + setnilvalue(L1->stack + i); /* erase new stack */ + L1->top = L1->stack; + L1->stack_last = L1->stack + L1->stacksize - EXTRA_STACK; + /* initialize first ci */ + ci = &L1->base_ci; + ci->next = ci->previous = NULL; + ci->callstatus = 0; + ci->func = L1->top; + setnilvalue(L1->top++); /* 'function' entry for this 'ci' */ + ci->top = L1->top + LUA_MINSTACK; + L1->ci = ci; +} + + +static void freestack (lua_State *L) { + if (L->stack == NULL) + return; /* stack not completely built yet */ + L->ci = &L->base_ci; /* free the entire 'ci' list */ + luaE_freeCI(L); + lua_assert(L->nci == 0); + luaM_freearray(L, L->stack, L->stacksize); /* free stack array */ +} + + +/* +** Create registry table and its predefined values +*/ +static void init_registry (lua_State *L, global_State *g) { + TValue temp; + /* create registry */ + Table *registry = luaH_new(L); + sethvalue(L, &g->l_registry, registry); + luaH_resize(L, registry, LUA_RIDX_LAST, 0); + /* registry[LUA_RIDX_MAINTHREAD] = L */ + setthvalue(L, &temp, L); /* temp = L */ + luaH_setint(L, registry, LUA_RIDX_MAINTHREAD, &temp); + /* registry[LUA_RIDX_GLOBALS] = table of globals */ + sethvalue(L, &temp, luaH_new(L)); /* temp = new table (global table) */ + luaH_setint(L, registry, LUA_RIDX_GLOBALS, &temp); +} + + +/* +** open parts of the state that may cause memory-allocation errors. +** ('g->version' != NULL flags that the state was completely build) +*/ +static void f_luaopen (lua_State *L, void *ud) { + global_State *g = G(L); + UNUSED(ud); + stack_init(L, L); /* init stack */ + init_registry(L, g); + luaS_init(L); + luaT_init(L); + luaX_init(L); + g->gcrunning = 1; /* allow gc */ + g->version = lua_version(NULL); + luai_userstateopen(L); +} + + +/* +** preinitialize a thread with consistent values without allocating +** any memory (to avoid errors) +*/ +static void preinit_thread (lua_State *L, global_State *g) { + G(L) = g; + L->stack = NULL; + L->ci = NULL; + L->nci = 0; + L->stacksize = 0; + L->twups = L; /* thread has no upvalues */ + L->errorJmp = NULL; + L->nCcalls = 0; + L->hook = NULL; + L->hookmask = 0; + L->basehookcount = 0; + L->allowhook = 1; + resethookcount(L); + L->openupval = NULL; + L->nny = 1; + L->status = LUA_OK; + L->errfunc = 0; +} + + +static void close_state (lua_State *L) { + global_State *g = G(L); + luaF_close(L, L->stack); /* close all upvalues for this thread */ + luaC_freeallobjects(L); /* collect all objects */ + if (g->version) /* closing a fully built state? */ + luai_userstateclose(L); + luaM_freearray(L, G(L)->strt.hash, G(L)->strt.size); + freestack(L); + lua_assert(gettotalbytes(g) == sizeof(LG)); + (*g->frealloc)(g->ud, fromstate(L), sizeof(LG), 0); /* free main block */ +} + + +LUA_API lua_State *lua_newthread (lua_State *L) { + global_State *g = G(L); + lua_State *L1; + lua_lock(L); + luaC_checkGC(L); + /* create new thread */ + L1 = &cast(LX *, luaM_newobject(L, LUA_TTHREAD, sizeof(LX)))->l; + L1->marked = luaC_white(g); + L1->tt = LUA_TTHREAD; + /* link it on list 'allgc' */ + L1->next = g->allgc; + g->allgc = obj2gco(L1); + /* anchor it on L stack */ + setthvalue(L, L->top, L1); + api_incr_top(L); + preinit_thread(L1, g); + L1->hookmask = L->hookmask; + L1->basehookcount = L->basehookcount; + L1->hook = L->hook; + resethookcount(L1); + /* initialize L1 extra space */ + memcpy(lua_getextraspace(L1), lua_getextraspace(g->mainthread), + LUA_EXTRASPACE); + luai_userstatethread(L, L1); + stack_init(L1, L); /* init stack */ + lua_unlock(L); + return L1; +} + + +void luaE_freethread (lua_State *L, lua_State *L1) { + LX *l = fromstate(L1); + luaF_close(L1, L1->stack); /* close all upvalues for this thread */ + lua_assert(L1->openupval == NULL); + luai_userstatefree(L, L1); + freestack(L1); + luaM_free(L, l); +} + + +LUA_API lua_State *lua_newstate (lua_Alloc f, void *ud) { + int i; + lua_State *L; + global_State *g; + LG *l = cast(LG *, (*f)(ud, NULL, LUA_TTHREAD, sizeof(LG))); + if (l == NULL) return NULL; + L = &l->l.l; + g = &l->g; + L->next = NULL; + L->tt = LUA_TTHREAD; + g->currentwhite = bitmask(WHITE0BIT); + L->marked = luaC_white(g); + preinit_thread(L, g); + g->frealloc = f; + g->ud = ud; + g->mainthread = L; + g->seed = makeseed(L); + g->gcrunning = 0; /* no GC while building state */ + g->GCestimate = 0; + g->strt.size = g->strt.nuse = 0; + g->strt.hash = NULL; + setnilvalue(&g->l_registry); + g->panic = NULL; + g->version = NULL; + g->gcstate = GCSpause; + g->gckind = KGC_NORMAL; + g->allgc = g->finobj = g->tobefnz = g->fixedgc = NULL; + g->sweepgc = NULL; + g->gray = g->grayagain = NULL; + g->weak = g->ephemeron = g->allweak = NULL; + g->twups = NULL; + g->totalbytes = sizeof(LG); + g->GCdebt = 0; + g->gcfinnum = 0; + g->gcpause = LUAI_GCPAUSE; + g->gcstepmul = LUAI_GCMUL; + for (i=0; i < LUA_NUMTAGS; i++) g->mt[i] = NULL; + if (luaD_rawrunprotected(L, f_luaopen, NULL) != LUA_OK) { + /* memory allocation error: free partial state */ + close_state(L); + L = NULL; + } + return L; +} + + +LUA_API void lua_close (lua_State *L) { + L = G(L)->mainthread; /* only the main thread can be closed */ + lua_lock(L); + close_state(L); +} + + diff --git a/src/lua/lstate.h b/src/lua/lstate.h new file mode 100644 index 000000000000..56b374100007 --- /dev/null +++ b/src/lua/lstate.h @@ -0,0 +1,253 @@ +/* +** $Id: lstate.h,v 2.133.1.1 2017/04/19 17:39:34 roberto Exp $ +** Global State +** See Copyright Notice in lua.h +*/ + +#ifndef lstate_h +#define lstate_h + +#include "lua.h" + +#include "lobject.h" +#include "ltm.h" +#include "lzio.h" + + +/* + +** Some notes about garbage-collected objects: All objects in Lua must +** be kept somehow accessible until being freed, so all objects always +** belong to one (and only one) of these lists, using field 'next' of +** the 'CommonHeader' for the link: +** +** 'allgc': all objects not marked for finalization; +** 'finobj': all objects marked for finalization; +** 'tobefnz': all objects ready to be finalized; +** 'fixedgc': all objects that are not to be collected (currently +** only small strings, such as reserved words). +** +** Moreover, there is another set of lists that control gray objects. +** These lists are linked by fields 'gclist'. (All objects that +** can become gray have such a field. The field is not the same +** in all objects, but it always has this name.) Any gray object +** must belong to one of these lists, and all objects in these lists +** must be gray: +** +** 'gray': regular gray objects, still waiting to be visited. +** 'grayagain': objects that must be revisited at the atomic phase. +** That includes +** - black objects got in a write barrier; +** - all kinds of weak tables during propagation phase; +** - all threads. +** 'weak': tables with weak values to be cleared; +** 'ephemeron': ephemeron tables with white->white entries; +** 'allweak': tables with weak keys and/or weak values to be cleared. +** The last three lists are used only during the atomic phase. + +*/ + + +struct lua_longjmp; /* defined in ldo.c */ + + +/* +** Atomic type (relative to signals) to better ensure that 'lua_sethook' +** is thread safe +*/ +#if !defined(l_signalT) +#include +#define l_signalT sig_atomic_t +#endif + + +/* extra stack space to handle TM calls and some other extras */ +#define EXTRA_STACK 5 + + +#define BASIC_STACK_SIZE (2*LUA_MINSTACK) + + +/* kinds of Garbage Collection */ +#define KGC_NORMAL 0 +#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ + + +typedef struct stringtable { + TString **hash; + int nuse; /* number of elements */ + int size; +} stringtable; + + +/* +** Information about a call. +** When a thread yields, 'func' is adjusted to pretend that the +** top function has only the yielded values in its stack; in that +** case, the actual 'func' value is saved in field 'extra'. +** When a function calls another with a continuation, 'extra' keeps +** the function index so that, in case of errors, the continuation +** function can be called with the correct top. +*/ +typedef struct CallInfo { + StkId func; /* function index in the stack */ + StkId top; /* top for this function */ + struct CallInfo *previous, *next; /* dynamic call link */ + union { + struct { /* only for Lua functions */ + StkId base; /* base for this function */ + const Instruction *savedpc; + } l; + struct { /* only for C functions */ + lua_KFunction k; /* continuation in case of yields */ + ptrdiff_t old_errfunc; + lua_KContext ctx; /* context info. in case of yields */ + } c; + } u; + ptrdiff_t extra; + short nresults; /* expected number of results from this function */ + unsigned short callstatus; +} CallInfo; + + +/* +** Bits in CallInfo status +*/ +#define CIST_OAH (1<<0) /* original value of 'allowhook' */ +#define CIST_LUA (1<<1) /* call is running a Lua function */ +#define CIST_HOOKED (1<<2) /* call is running a debug hook */ +#define CIST_FRESH (1<<3) /* call is running on a fresh invocation + of luaV_execute */ +#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ +#define CIST_TAIL (1<<5) /* call was tail called */ +#define CIST_HOOKYIELD (1<<6) /* last hook called yielded */ +#define CIST_LEQ (1<<7) /* using __lt for __le */ +#define CIST_FIN (1<<8) /* call is running a finalizer */ + +#define isLua(ci) ((ci)->callstatus & CIST_LUA) + +/* assume that CIST_OAH has offset 0 and that 'v' is strictly 0/1 */ +#define setoah(st,v) ((st) = ((st) & ~CIST_OAH) | (v)) +#define getoah(st) ((st) & CIST_OAH) + + +/* +** 'global state', shared by all threads of this state +*/ +typedef struct global_State { + lua_Alloc frealloc; /* function to reallocate memory */ + void *ud; /* auxiliary data to 'frealloc' */ + l_mem totalbytes; /* number of bytes currently allocated - GCdebt */ + l_mem GCdebt; /* bytes allocated not yet compensated by the collector */ + lu_mem GCmemtrav; /* memory traversed by the GC */ + lu_mem GCestimate; /* an estimate of the non-garbage memory in use */ + stringtable strt; /* hash table for strings */ + TValue l_registry; + unsigned int seed; /* randomized seed for hashes */ + lu_byte currentwhite; + lu_byte gcstate; /* state of garbage collector */ + lu_byte gckind; /* kind of GC running */ + lu_byte gcrunning; /* true if GC is running */ + GCObject *allgc; /* list of all collectable objects */ + GCObject **sweepgc; /* current position of sweep in list */ + GCObject *finobj; /* list of collectable objects with finalizers */ + GCObject *gray; /* list of gray objects */ + GCObject *grayagain; /* list of objects to be traversed atomically */ + GCObject *weak; /* list of tables with weak values */ + GCObject *ephemeron; /* list of ephemeron tables (weak keys) */ + GCObject *allweak; /* list of all-weak tables */ + GCObject *tobefnz; /* list of userdata to be GC */ + GCObject *fixedgc; /* list of objects not to be collected */ + struct lua_State *twups; /* list of threads with open upvalues */ + unsigned int gcfinnum; /* number of finalizers to call in each GC step */ + int gcpause; /* size of pause between successive GCs */ + int gcstepmul; /* GC 'granularity' */ + lua_CFunction panic; /* to be called in unprotected errors */ + struct lua_State *mainthread; + const lua_Number *version; /* pointer to version number */ + TString *memerrmsg; /* memory-error message */ + TString *tmname[TM_N]; /* array with tag-method names */ + struct Table *mt[LUA_NUMTAGS]; /* metatables for basic types */ + TString *strcache[STRCACHE_N][STRCACHE_M]; /* cache for strings in API */ +} global_State; + + +/* +** 'per thread' state +*/ +struct lua_State { + CommonHeader; + unsigned short nci; /* number of items in 'ci' list */ + lu_byte status; + StkId top; /* first free slot in the stack */ + global_State *l_G; + CallInfo *ci; /* call info for current function */ + const Instruction *oldpc; /* last pc traced */ + StkId stack_last; /* last free slot in the stack */ + StkId stack; /* stack base */ + UpVal *openupval; /* list of open upvalues in this stack */ + GCObject *gclist; + struct lua_State *twups; /* list of threads with open upvalues */ + struct lua_longjmp *errorJmp; /* current error recover point */ + CallInfo base_ci; /* CallInfo for first level (C calling Lua) */ + volatile lua_Hook hook; + ptrdiff_t errfunc; /* current error handling function (stack index) */ + int stacksize; + int basehookcount; + int hookcount; + unsigned short nny; /* number of non-yieldable calls in stack */ + unsigned short nCcalls; /* number of nested C calls */ + l_signalT hookmask; + lu_byte allowhook; +}; + + +#define G(L) (L->l_G) + + +/* +** Union of all collectable objects (only for conversions) +*/ +union GCUnion { + GCObject gc; /* common header */ + struct TString ts; + struct Udata u; + union Closure cl; + struct Table h; + struct Proto p; + struct lua_State th; /* thread */ +}; + + +#define cast_u(o) cast(union GCUnion *, (o)) + +/* macros to convert a GCObject into a specific value */ +#define gco2ts(o) \ + check_exp(novariant((o)->tt) == LUA_TSTRING, &((cast_u(o))->ts)) +#define gco2u(o) check_exp((o)->tt == LUA_TUSERDATA, &((cast_u(o))->u)) +#define gco2lcl(o) check_exp((o)->tt == LUA_TLCL, &((cast_u(o))->cl.l)) +#define gco2ccl(o) check_exp((o)->tt == LUA_TCCL, &((cast_u(o))->cl.c)) +#define gco2cl(o) \ + check_exp(novariant((o)->tt) == LUA_TFUNCTION, &((cast_u(o))->cl)) +#define gco2t(o) check_exp((o)->tt == LUA_TTABLE, &((cast_u(o))->h)) +#define gco2p(o) check_exp((o)->tt == LUA_TPROTO, &((cast_u(o))->p)) +#define gco2th(o) check_exp((o)->tt == LUA_TTHREAD, &((cast_u(o))->th)) + + +/* macro to convert a Lua object into a GCObject */ +#define obj2gco(v) \ + check_exp(novariant((v)->tt) < LUA_TDEADKEY, (&(cast_u(v)->gc))) + + +/* actual number of total bytes allocated */ +#define gettotalbytes(g) cast(lu_mem, (g)->totalbytes + (g)->GCdebt) + +LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); +LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); +LUAI_FUNC CallInfo *luaE_extendCI (lua_State *L); +LUAI_FUNC void luaE_freeCI (lua_State *L); +LUAI_FUNC void luaE_shrinkCI (lua_State *L); + + +#endif + diff --git a/src/lua/lstring.c b/src/lua/lstring.c new file mode 100644 index 000000000000..6257f211d9e7 --- /dev/null +++ b/src/lua/lstring.c @@ -0,0 +1,248 @@ +/* +** $Id: lstring.c,v 2.56.1.1 2017/04/19 17:20:42 roberto Exp $ +** String table (keeps all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#define lstring_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" + + +#define MEMERRMSG "not enough memory" + + +/* +** Lua will use at most ~(2^LUAI_HASHLIMIT) bytes from a string to +** compute its hash +*/ +#if !defined(LUAI_HASHLIMIT) +#define LUAI_HASHLIMIT 5 +#endif + + +/* +** equality for long strings +*/ +int luaS_eqlngstr (TString *a, TString *b) { + size_t len = a->u.lnglen; + lua_assert(a->tt == LUA_TLNGSTR && b->tt == LUA_TLNGSTR); + return (a == b) || /* same instance or... */ + ((len == b->u.lnglen) && /* equal length and ... */ + (memcmp(getstr(a), getstr(b), len) == 0)); /* equal contents */ +} + + +unsigned int luaS_hash (const char *str, size_t l, unsigned int seed) { + unsigned int h = seed ^ cast(unsigned int, l); + size_t step = (l >> LUAI_HASHLIMIT) + 1; + for (; l >= step; l -= step) + h ^= ((h<<5) + (h>>2) + cast_byte(str[l - 1])); + return h; +} + + +unsigned int luaS_hashlongstr (TString *ts) { + lua_assert(ts->tt == LUA_TLNGSTR); + if (ts->extra == 0) { /* no hash? */ + ts->hash = luaS_hash(getstr(ts), ts->u.lnglen, ts->hash); + ts->extra = 1; /* now it has its hash */ + } + return ts->hash; +} + + +/* +** resizes the string table +*/ +void luaS_resize (lua_State *L, int newsize) { + int i; + stringtable *tb = &G(L)->strt; + if (newsize > tb->size) { /* grow table if needed */ + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + for (i = tb->size; i < newsize; i++) + tb->hash[i] = NULL; + } + for (i = 0; i < tb->size; i++) { /* rehash */ + TString *p = tb->hash[i]; + tb->hash[i] = NULL; + while (p) { /* for each node in the list */ + TString *hnext = p->u.hnext; /* save next */ + unsigned int h = lmod(p->hash, newsize); /* new position */ + p->u.hnext = tb->hash[h]; /* chain it */ + tb->hash[h] = p; + p = hnext; + } + } + if (newsize < tb->size) { /* shrink table if needed */ + /* vanishing slice should be empty */ + lua_assert(tb->hash[newsize] == NULL && tb->hash[tb->size - 1] == NULL); + luaM_reallocvector(L, tb->hash, tb->size, newsize, TString *); + } + tb->size = newsize; +} + + +/* +** Clear API string cache. (Entries cannot be empty, so fill them with +** a non-collectable string.) +*/ +void luaS_clearcache (global_State *g) { + int i, j; + for (i = 0; i < STRCACHE_N; i++) + for (j = 0; j < STRCACHE_M; j++) { + if (iswhite(g->strcache[i][j])) /* will entry be collected? */ + g->strcache[i][j] = g->memerrmsg; /* replace it with something fixed */ + } +} + + +/* +** Initialize the string table and the string cache +*/ +void luaS_init (lua_State *L) { + global_State *g = G(L); + int i, j; + luaS_resize(L, MINSTRTABSIZE); /* initial size of string table */ + /* pre-create memory-error message */ + g->memerrmsg = luaS_newliteral(L, MEMERRMSG); + luaC_fix(L, obj2gco(g->memerrmsg)); /* it should never be collected */ + for (i = 0; i < STRCACHE_N; i++) /* fill cache with valid strings */ + for (j = 0; j < STRCACHE_M; j++) + g->strcache[i][j] = g->memerrmsg; +} + + + +/* +** creates a new string object +*/ +static TString *createstrobj (lua_State *L, size_t l, int tag, unsigned int h) { + TString *ts; + GCObject *o; + size_t totalsize; /* total size of TString object */ + totalsize = sizelstring(l); + o = luaC_newobj(L, tag, totalsize); + ts = gco2ts(o); + ts->hash = h; + ts->extra = 0; + getstr(ts)[l] = '\0'; /* ending 0 */ + return ts; +} + + +TString *luaS_createlngstrobj (lua_State *L, size_t l) { + TString *ts = createstrobj(L, l, LUA_TLNGSTR, G(L)->seed); + ts->u.lnglen = l; + return ts; +} + + +void luaS_remove (lua_State *L, TString *ts) { + stringtable *tb = &G(L)->strt; + TString **p = &tb->hash[lmod(ts->hash, tb->size)]; + while (*p != ts) /* find previous element */ + p = &(*p)->u.hnext; + *p = (*p)->u.hnext; /* remove element from its list */ + tb->nuse--; +} + + +/* +** checks whether short string exists and reuses it or creates a new one +*/ +static TString *internshrstr (lua_State *L, const char *str, size_t l) { + TString *ts; + global_State *g = G(L); + unsigned int h = luaS_hash(str, l, g->seed); + TString **list = &g->strt.hash[lmod(h, g->strt.size)]; + lua_assert(str != NULL); /* otherwise 'memcmp'/'memcpy' are undefined */ + for (ts = *list; ts != NULL; ts = ts->u.hnext) { + if (l == ts->shrlen && + (memcmp(str, getstr(ts), l * sizeof(char)) == 0)) { + /* found! */ + if (isdead(g, ts)) /* dead (but not collected yet)? */ + changewhite(ts); /* resurrect it */ + return ts; + } + } + if (g->strt.nuse >= g->strt.size && g->strt.size <= MAX_INT/2) { + luaS_resize(L, g->strt.size * 2); + list = &g->strt.hash[lmod(h, g->strt.size)]; /* recompute with new size */ + } + ts = createstrobj(L, l, LUA_TSHRSTR, h); + memcpy(getstr(ts), str, l * sizeof(char)); + ts->shrlen = cast_byte(l); + ts->u.hnext = *list; + *list = ts; + g->strt.nuse++; + return ts; +} + + +/* +** new string (with explicit length) +*/ +TString *luaS_newlstr (lua_State *L, const char *str, size_t l) { + if (l <= LUAI_MAXSHORTLEN) /* short string? */ + return internshrstr(L, str, l); + else { + TString *ts; + if (l >= (MAX_SIZE - sizeof(TString))/sizeof(char)) + luaM_toobig(L); + ts = luaS_createlngstrobj(L, l); + memcpy(getstr(ts), str, l * sizeof(char)); + return ts; + } +} + + +/* +** Create or reuse a zero-terminated string, first checking in the +** cache (using the string address as a key). The cache can contain +** only zero-terminated strings, so it is safe to use 'strcmp' to +** check hits. +*/ +TString *luaS_new (lua_State *L, const char *str) { + unsigned int i = point2uint(str) % STRCACHE_N; /* hash */ + int j; + TString **p = G(L)->strcache[i]; + for (j = 0; j < STRCACHE_M; j++) { + if (strcmp(str, getstr(p[j])) == 0) /* hit? */ + return p[j]; /* that is it */ + } + /* normal route */ + for (j = STRCACHE_M - 1; j > 0; j--) + p[j] = p[j - 1]; /* move out last element */ + /* new element is first in the list */ + p[0] = luaS_newlstr(L, str, strlen(str)); + return p[0]; +} + + +Udata *luaS_newudata (lua_State *L, size_t s) { + Udata *u; + GCObject *o; + if (s > MAX_SIZE - sizeof(Udata)) + luaM_toobig(L); + o = luaC_newobj(L, LUA_TUSERDATA, sizeludata(s)); + u = gco2u(o); + u->len = s; + u->metatable = NULL; + setuservalue(L, u, luaO_nilobject); + return u; +} + diff --git a/src/lua/lstring.h b/src/lua/lstring.h new file mode 100644 index 000000000000..d612abd3332f --- /dev/null +++ b/src/lua/lstring.h @@ -0,0 +1,49 @@ +/* +** $Id: lstring.h,v 1.61.1.1 2017/04/19 17:20:42 roberto Exp $ +** String table (keep all strings handled by Lua) +** See Copyright Notice in lua.h +*/ + +#ifndef lstring_h +#define lstring_h + +#include "lgc.h" +#include "lobject.h" +#include "lstate.h" + + +#define sizelstring(l) (sizeof(union UTString) + ((l) + 1) * sizeof(char)) + +#define sizeludata(l) (sizeof(union UUdata) + (l)) +#define sizeudata(u) sizeludata((u)->len) + +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ + (sizeof(s)/sizeof(char))-1)) + + +/* +** test whether a string is a reserved word +*/ +#define isreserved(s) ((s)->tt == LUA_TSHRSTR && (s)->extra > 0) + + +/* +** equality for short strings, which are always internalized +*/ +#define eqshrstr(a,b) check_exp((a)->tt == LUA_TSHRSTR, (a) == (b)) + + +LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); +LUAI_FUNC unsigned int luaS_hashlongstr (TString *ts); +LUAI_FUNC int luaS_eqlngstr (TString *a, TString *b); +LUAI_FUNC void luaS_resize (lua_State *L, int newsize); +LUAI_FUNC void luaS_clearcache (global_State *g); +LUAI_FUNC void luaS_init (lua_State *L); +LUAI_FUNC void luaS_remove (lua_State *L, TString *ts); +LUAI_FUNC Udata *luaS_newudata (lua_State *L, size_t s); +LUAI_FUNC TString *luaS_newlstr (lua_State *L, const char *str, size_t l); +LUAI_FUNC TString *luaS_new (lua_State *L, const char *str); +LUAI_FUNC TString *luaS_createlngstrobj (lua_State *L, size_t l); + + +#endif diff --git a/src/lua/lstrlib.c b/src/lua/lstrlib.c new file mode 100644 index 000000000000..b4bed7e93d1c --- /dev/null +++ b/src/lua/lstrlib.c @@ -0,0 +1,1584 @@ +/* +** $Id: lstrlib.c,v 1.254.1.1 2017/04/19 17:29:57 roberto Exp $ +** Standard library for string operations and pattern-matching +** See Copyright Notice in lua.h +*/ + +#define lstrlib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** maximum number of captures that a pattern can do during +** pattern-matching. This limit is arbitrary, but must fit in +** an unsigned char. +*/ +#if !defined(LUA_MAXCAPTURES) +#define LUA_MAXCAPTURES 32 +#endif + + +/* macro to 'unsign' a character */ +#define uchar(c) ((unsigned char)(c)) + + +/* +** Some sizes are better limited to fit in 'int', but must also fit in +** 'size_t'. (We assume that 'lua_Integer' cannot be smaller than 'int'.) +*/ +#define MAX_SIZET ((size_t)(~(size_t)0)) + +#define MAXSIZE \ + (sizeof(size_t) < sizeof(int) ? MAX_SIZET : (size_t)(INT_MAX)) + + + + +static int str_len (lua_State *L) { + size_t l; + luaL_checklstring(L, 1, &l); + lua_pushinteger(L, (lua_Integer)l); + return 1; +} + + +/* translate a relative string position: negative means back from end */ +static lua_Integer posrelat (lua_Integer pos, size_t len) { + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; +} + + +static int str_sub (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + lua_Integer start = posrelat(luaL_checkinteger(L, 2), l); + lua_Integer end = posrelat(luaL_optinteger(L, 3, -1), l); + if (start < 1) start = 1; + if (end > (lua_Integer)l) end = l; + if (start <= end) + lua_pushlstring(L, s + start - 1, (size_t)(end - start) + 1); + else lua_pushliteral(L, ""); + return 1; +} + + +static int str_reverse (lua_State *L) { + size_t l, i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + char *p = luaL_buffinitsize(L, &b, l); + for (i = 0; i < l; i++) + p[i] = s[l - i - 1]; + luaL_pushresultsize(&b, l); + return 1; +} + + +static int str_lower (lua_State *L) { + size_t l; + size_t i; + luaL_Buffer b; + const char *s = luaL_checklstring(L, 1, &l); + char *p = luaL_buffinitsize(L, &b, l); + for (i=0; i MAXSIZE / n) /* may overflow? */ + return luaL_error(L, "resulting string too large"); + else { + size_t totallen = (size_t)n * l + (size_t)(n - 1) * lsep; + luaL_Buffer b; + char *p = luaL_buffinitsize(L, &b, totallen); + while (n-- > 1) { /* first n-1 copies (followed by separator) */ + memcpy(p, s, l * sizeof(char)); p += l; + if (lsep > 0) { /* empty 'memcpy' is not that cheap */ + memcpy(p, sep, lsep * sizeof(char)); + p += lsep; + } + } + memcpy(p, s, l * sizeof(char)); /* last copy (not followed by separator) */ + luaL_pushresultsize(&b, totallen); + } + return 1; +} + + +static int str_byte (lua_State *L) { + size_t l; + const char *s = luaL_checklstring(L, 1, &l); + lua_Integer posi = posrelat(luaL_optinteger(L, 2, 1), l); + lua_Integer pose = posrelat(luaL_optinteger(L, 3, posi), l); + int n, i; + if (posi < 1) posi = 1; + if (pose > (lua_Integer)l) pose = l; + if (posi > pose) return 0; /* empty interval; return no values */ + if (pose - posi >= INT_MAX) /* arithmetic overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; + luaL_checkstack(L, n, "string slice too long"); + for (i=0; i= ms->level || ms->capture[l].len == CAP_UNFINISHED) + return luaL_error(ms->L, "invalid capture index %%%d", l + 1); + return l; +} + + +static int capture_to_close (MatchState *ms) { + int level = ms->level; + for (level--; level>=0; level--) + if (ms->capture[level].len == CAP_UNFINISHED) return level; + return luaL_error(ms->L, "invalid pattern capture"); +} + + +static const char *classend (MatchState *ms, const char *p) { + switch (*p++) { + case L_ESC: { + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (ends with '%%')"); + return p+1; + } + case '[': { + if (*p == '^') p++; + do { /* look for a ']' */ + if (p == ms->p_end) + luaL_error(ms->L, "malformed pattern (missing ']')"); + if (*(p++) == L_ESC && p < ms->p_end) + p++; /* skip escapes (e.g. '%]') */ + } while (*p != ']'); + return p+1; + } + default: { + return p; + } + } +} + + +static int match_class (int c, int cl) { + int res; + switch (tolower(cl)) { + case 'a' : res = isalpha(c); break; + case 'c' : res = iscntrl(c); break; + case 'd' : res = isdigit(c); break; + case 'g' : res = isgraph(c); break; + case 'l' : res = islower(c); break; + case 'p' : res = ispunct(c); break; + case 's' : res = isspace(c); break; + case 'u' : res = isupper(c); break; + case 'w' : res = isalnum(c); break; + case 'x' : res = isxdigit(c); break; + case 'z' : res = (c == 0); break; /* deprecated option */ + default: return (cl == c); + } + return (islower(cl) ? res : !res); +} + + +static int matchbracketclass (int c, const char *p, const char *ec) { + int sig = 1; + if (*(p+1) == '^') { + sig = 0; + p++; /* skip the '^' */ + } + while (++p < ec) { + if (*p == L_ESC) { + p++; + if (match_class(c, uchar(*p))) + return sig; + } + else if ((*(p+1) == '-') && (p+2 < ec)) { + p+=2; + if (uchar(*(p-2)) <= c && c <= uchar(*p)) + return sig; + } + else if (uchar(*p) == c) return sig; + } + return !sig; +} + + +static int singlematch (MatchState *ms, const char *s, const char *p, + const char *ep) { + if (s >= ms->src_end) + return 0; + else { + int c = uchar(*s); + switch (*p) { + case '.': return 1; /* matches any char */ + case L_ESC: return match_class(c, uchar(*(p+1))); + case '[': return matchbracketclass(c, p, ep-1); + default: return (uchar(*p) == c); + } + } +} + + +static const char *matchbalance (MatchState *ms, const char *s, + const char *p) { + if (p >= ms->p_end - 1) + luaL_error(ms->L, "malformed pattern (missing arguments to '%%b')"); + if (*s != *p) return NULL; + else { + int b = *p; + int e = *(p+1); + int cont = 1; + while (++s < ms->src_end) { + if (*s == e) { + if (--cont == 0) return s+1; + } + else if (*s == b) cont++; + } + } + return NULL; /* string ends out of balance */ +} + + +static const char *max_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + ptrdiff_t i = 0; /* counts maximum expand for item */ + while (singlematch(ms, s + i, p, ep)) + i++; + /* keeps trying to match with the maximum repetitions */ + while (i>=0) { + const char *res = match(ms, (s+i), ep+1); + if (res) return res; + i--; /* else didn't match; reduce 1 repetition to try again */ + } + return NULL; +} + + +static const char *min_expand (MatchState *ms, const char *s, + const char *p, const char *ep) { + for (;;) { + const char *res = match(ms, s, ep+1); + if (res != NULL) + return res; + else if (singlematch(ms, s, p, ep)) + s++; /* try with one more repetition */ + else return NULL; + } +} + + +static const char *start_capture (MatchState *ms, const char *s, + const char *p, int what) { + const char *res; + int level = ms->level; + if (level >= LUA_MAXCAPTURES) luaL_error(ms->L, "too many captures"); + ms->capture[level].init = s; + ms->capture[level].len = what; + ms->level = level+1; + if ((res=match(ms, s, p)) == NULL) /* match failed? */ + ms->level--; /* undo capture */ + return res; +} + + +static const char *end_capture (MatchState *ms, const char *s, + const char *p) { + int l = capture_to_close(ms); + const char *res; + ms->capture[l].len = s - ms->capture[l].init; /* close capture */ + if ((res = match(ms, s, p)) == NULL) /* match failed? */ + ms->capture[l].len = CAP_UNFINISHED; /* undo capture */ + return res; +} + + +static const char *match_capture (MatchState *ms, const char *s, int l) { + size_t len; + l = check_capture(ms, l); + len = ms->capture[l].len; + if ((size_t)(ms->src_end-s) >= len && + memcmp(ms->capture[l].init, s, len) == 0) + return s+len; + else return NULL; +} + + +static const char *match (MatchState *ms, const char *s, const char *p) { + if (ms->matchdepth-- == 0) + luaL_error(ms->L, "pattern too complex"); + init: /* using goto's to optimize tail recursion */ + if (p != ms->p_end) { /* end of pattern? */ + switch (*p) { + case '(': { /* start capture */ + if (*(p + 1) == ')') /* position capture? */ + s = start_capture(ms, s, p + 2, CAP_POSITION); + else + s = start_capture(ms, s, p + 1, CAP_UNFINISHED); + break; + } + case ')': { /* end capture */ + s = end_capture(ms, s, p + 1); + break; + } + case '$': { + if ((p + 1) != ms->p_end) /* is the '$' the last char in pattern? */ + goto dflt; /* no; go to default */ + s = (s == ms->src_end) ? s : NULL; /* check end of string */ + break; + } + case L_ESC: { /* escaped sequences not in the format class[*+?-]? */ + switch (*(p + 1)) { + case 'b': { /* balanced string? */ + s = matchbalance(ms, s, p + 2); + if (s != NULL) { + p += 4; goto init; /* return match(ms, s, p + 4); */ + } /* else fail (s == NULL) */ + break; + } + case 'f': { /* frontier? */ + const char *ep; char previous; + p += 2; + if (*p != '[') + luaL_error(ms->L, "missing '[' after '%%f' in pattern"); + ep = classend(ms, p); /* points to what is next */ + previous = (s == ms->src_init) ? '\0' : *(s - 1); + if (!matchbracketclass(uchar(previous), p, ep - 1) && + matchbracketclass(uchar(*s), p, ep - 1)) { + p = ep; goto init; /* return match(ms, s, ep); */ + } + s = NULL; /* match failed */ + break; + } + case '0': case '1': case '2': case '3': + case '4': case '5': case '6': case '7': + case '8': case '9': { /* capture results (%0-%9)? */ + s = match_capture(ms, s, uchar(*(p + 1))); + if (s != NULL) { + p += 2; goto init; /* return match(ms, s, p + 2) */ + } + break; + } + default: goto dflt; + } + break; + } + default: dflt: { /* pattern class plus optional suffix */ + const char *ep = classend(ms, p); /* points to optional suffix */ + /* does not match at least once? */ + if (!singlematch(ms, s, p, ep)) { + if (*ep == '*' || *ep == '?' || *ep == '-') { /* accept empty? */ + p = ep + 1; goto init; /* return match(ms, s, ep + 1); */ + } + else /* '+' or no suffix */ + s = NULL; /* fail */ + } + else { /* matched once */ + switch (*ep) { /* handle optional suffix */ + case '?': { /* optional */ + const char *res; + if ((res = match(ms, s + 1, ep + 1)) != NULL) + s = res; + else { + p = ep + 1; goto init; /* else return match(ms, s, ep + 1); */ + } + break; + } + case '+': /* 1 or more repetitions */ + s++; /* 1 match already done */ + /* FALLTHROUGH */ + case '*': /* 0 or more repetitions */ + s = max_expand(ms, s, p, ep); + break; + case '-': /* 0 or more repetitions (minimum) */ + s = min_expand(ms, s, p, ep); + break; + default: /* no suffix */ + s++; p = ep; goto init; /* return match(ms, s + 1, ep); */ + } + } + break; + } + } + } + ms->matchdepth++; + return s; +} + + + +static const char *lmemfind (const char *s1, size_t l1, + const char *s2, size_t l2) { + if (l2 == 0) return s1; /* empty strings are everywhere */ + else if (l2 > l1) return NULL; /* avoids a negative 'l1' */ + else { + const char *init; /* to search for a '*s2' inside 's1' */ + l2--; /* 1st char will be checked by 'memchr' */ + l1 = l1-l2; /* 's2' cannot be found after that */ + while (l1 > 0 && (init = (const char *)memchr(s1, *s2, l1)) != NULL) { + init++; /* 1st char is already checked */ + if (memcmp(init, s2+1, l2) == 0) + return init-1; + else { /* correct 'l1' and 's1' to try again */ + l1 -= init-s1; + s1 = init; + } + } + return NULL; /* not found */ + } +} + + +static void push_onecapture (MatchState *ms, int i, const char *s, + const char *e) { + if (i >= ms->level) { + if (i == 0) /* ms->level == 0, too */ + lua_pushlstring(ms->L, s, e - s); /* add whole match */ + else + luaL_error(ms->L, "invalid capture index %%%d", i + 1); + } + else { + ptrdiff_t l = ms->capture[i].len; + if (l == CAP_UNFINISHED) luaL_error(ms->L, "unfinished capture"); + if (l == CAP_POSITION) + lua_pushinteger(ms->L, (ms->capture[i].init - ms->src_init) + 1); + else + lua_pushlstring(ms->L, ms->capture[i].init, l); + } +} + + +static int push_captures (MatchState *ms, const char *s, const char *e) { + int i; + int nlevels = (ms->level == 0 && s) ? 1 : ms->level; + luaL_checkstack(ms->L, nlevels, "too many captures"); + for (i = 0; i < nlevels; i++) + push_onecapture(ms, i, s, e); + return nlevels; /* number of strings pushed */ +} + + +/* check whether pattern has no special characters */ +static int nospecials (const char *p, size_t l) { + size_t upto = 0; + do { + if (strpbrk(p + upto, SPECIALS)) + return 0; /* pattern has a special character */ + upto += strlen(p + upto) + 1; /* may have more after \0 */ + } while (upto <= l); + return 1; /* no special chars found */ +} + + +static void prepstate (MatchState *ms, lua_State *L, + const char *s, size_t ls, const char *p, size_t lp) { + ms->L = L; + ms->matchdepth = MAXCCALLS; + ms->src_init = s; + ms->src_end = s + ls; + ms->p_end = p + lp; +} + + +static void reprepstate (MatchState *ms) { + ms->level = 0; + lua_assert(ms->matchdepth == MAXCCALLS); +} + + +static int str_find_aux (lua_State *L, int find) { + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + lua_Integer init = posrelat(luaL_optinteger(L, 3, 1), ls); + if (init < 1) init = 1; + else if (init > (lua_Integer)ls + 1) { /* start after string's end? */ + lua_pushnil(L); /* cannot find anything */ + return 1; + } + /* explicit request or no special characters? */ + if (find && (lua_toboolean(L, 4) || nospecials(p, lp))) { + /* do a plain search */ + const char *s2 = lmemfind(s + init - 1, ls - (size_t)init + 1, p, lp); + if (s2) { + lua_pushinteger(L, (s2 - s) + 1); + lua_pushinteger(L, (s2 - s) + lp); + return 2; + } + } + else { + MatchState ms; + const char *s1 = s + init - 1; + int anchor = (*p == '^'); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + prepstate(&ms, L, s, ls, p, lp); + do { + const char *res; + reprepstate(&ms); + if ((res=match(&ms, s1, p)) != NULL) { + if (find) { + lua_pushinteger(L, (s1 - s) + 1); /* start */ + lua_pushinteger(L, res - s); /* end */ + return push_captures(&ms, NULL, 0) + 2; + } + else + return push_captures(&ms, s1, res); + } + } while (s1++ < ms.src_end && !anchor); + } + lua_pushnil(L); /* not found */ + return 1; +} + + +static int str_find (lua_State *L) { + return str_find_aux(L, 1); +} + + +static int str_match (lua_State *L) { + return str_find_aux(L, 0); +} + + +/* state for 'gmatch' */ +typedef struct GMatchState { + const char *src; /* current position */ + const char *p; /* pattern */ + const char *lastmatch; /* end of last match */ + MatchState ms; /* match state */ +} GMatchState; + + +static int gmatch_aux (lua_State *L) { + GMatchState *gm = (GMatchState *)lua_touserdata(L, lua_upvalueindex(3)); + const char *src; + gm->ms.L = L; + for (src = gm->src; src <= gm->ms.src_end; src++) { + const char *e; + reprepstate(&gm->ms); + if ((e = match(&gm->ms, src, gm->p)) != NULL && e != gm->lastmatch) { + gm->src = gm->lastmatch = e; + return push_captures(&gm->ms, src, e); + } + } + return 0; /* not found */ +} + + +static int gmatch (lua_State *L) { + size_t ls, lp; + const char *s = luaL_checklstring(L, 1, &ls); + const char *p = luaL_checklstring(L, 2, &lp); + GMatchState *gm; + lua_settop(L, 2); /* keep them on closure to avoid being collected */ + gm = (GMatchState *)lua_newuserdata(L, sizeof(GMatchState)); + prepstate(&gm->ms, L, s, ls, p, lp); + gm->src = s; gm->p = p; gm->lastmatch = NULL; + lua_pushcclosure(L, gmatch_aux, 3); + return 1; +} + + +static void add_s (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e) { + size_t l, i; + lua_State *L = ms->L; + const char *news = lua_tolstring(L, 3, &l); + for (i = 0; i < l; i++) { + if (news[i] != L_ESC) + luaL_addchar(b, news[i]); + else { + i++; /* skip ESC */ + if (!isdigit(uchar(news[i]))) { + if (news[i] != L_ESC) + luaL_error(L, "invalid use of '%c' in replacement string", L_ESC); + luaL_addchar(b, news[i]); + } + else if (news[i] == '0') + luaL_addlstring(b, s, e - s); + else { + push_onecapture(ms, news[i] - '1', s, e); + luaL_tolstring(L, -1, NULL); /* if number, convert it to string */ + lua_remove(L, -2); /* remove original value */ + luaL_addvalue(b); /* add capture to accumulated result */ + } + } + } +} + + +static void add_value (MatchState *ms, luaL_Buffer *b, const char *s, + const char *e, int tr) { + lua_State *L = ms->L; + switch (tr) { + case LUA_TFUNCTION: { + int n; + lua_pushvalue(L, 3); + n = push_captures(ms, s, e); + lua_call(L, n, 1); + break; + } + case LUA_TTABLE: { + push_onecapture(ms, 0, s, e); + lua_gettable(L, 3); + break; + } + default: { /* LUA_TNUMBER or LUA_TSTRING */ + add_s(ms, b, s, e); + return; + } + } + if (!lua_toboolean(L, -1)) { /* nil or false? */ + lua_pop(L, 1); + lua_pushlstring(L, s, e - s); /* keep original text */ + } + else if (!lua_isstring(L, -1)) + luaL_error(L, "invalid replacement value (a %s)", luaL_typename(L, -1)); + luaL_addvalue(b); /* add result to accumulator */ +} + + +static int str_gsub (lua_State *L) { + size_t srcl, lp; + const char *src = luaL_checklstring(L, 1, &srcl); /* subject */ + const char *p = luaL_checklstring(L, 2, &lp); /* pattern */ + const char *lastmatch = NULL; /* end of last match */ + int tr = lua_type(L, 3); /* replacement type */ + lua_Integer max_s = luaL_optinteger(L, 4, srcl + 1); /* max replacements */ + int anchor = (*p == '^'); + lua_Integer n = 0; /* replacement count */ + MatchState ms; + luaL_Buffer b; + luaL_argcheck(L, tr == LUA_TNUMBER || tr == LUA_TSTRING || + tr == LUA_TFUNCTION || tr == LUA_TTABLE, 3, + "string/function/table expected"); + luaL_buffinit(L, &b); + if (anchor) { + p++; lp--; /* skip anchor character */ + } + prepstate(&ms, L, src, srcl, p, lp); + while (n < max_s) { + const char *e; + reprepstate(&ms); /* (re)prepare state for new match */ + if ((e = match(&ms, src, p)) != NULL && e != lastmatch) { /* match? */ + n++; + add_value(&ms, &b, src, e, tr); /* add replacement to buffer */ + src = lastmatch = e; + } + else if (src < ms.src_end) /* otherwise, skip one character */ + luaL_addchar(&b, *src++); + else break; /* end of subject */ + if (anchor) break; + } + luaL_addlstring(&b, src, ms.src_end-src); + luaL_pushresult(&b); + lua_pushinteger(L, n); /* number of substitutions */ + return 2; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** STRING FORMAT +** ======================================================= +*/ + +#if !defined(lua_number2strx) /* { */ + +/* +** Hexadecimal floating-point formatter +*/ + +#include + +#define SIZELENMOD (sizeof(LUA_NUMBER_FRMLEN)/sizeof(char)) + + +/* +** Number of bits that goes into the first digit. It can be any value +** between 1 and 4; the following definition tries to align the number +** to nibble boundaries by making what is left after that first digit a +** multiple of 4. +*/ +#define L_NBFD ((l_mathlim(MANT_DIG) - 1)%4 + 1) + + +/* +** Add integer part of 'x' to buffer and return new 'x' +*/ +static lua_Number adddigit (char *buff, int n, lua_Number x) { + lua_Number dd = l_mathop(floor)(x); /* get integer part from 'x' */ + int d = (int)dd; + buff[n] = (d < 10 ? d + '0' : d - 10 + 'a'); /* add to buffer */ + return x - dd; /* return what is left */ +} + + +static int num2straux (char *buff, int sz, lua_Number x) { + /* if 'inf' or 'NaN', format it like '%g' */ + if (x != x || x == (lua_Number)HUGE_VAL || x == -(lua_Number)HUGE_VAL) + return l_sprintf(buff, sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)x); + else if (x == 0) { /* can be -0... */ + /* create "0" or "-0" followed by exponent */ + return l_sprintf(buff, sz, LUA_NUMBER_FMT "x0p+0", (LUAI_UACNUMBER)x); + } + else { + int e; + lua_Number m = l_mathop(frexp)(x, &e); /* 'x' fraction and exponent */ + int n = 0; /* character count */ + if (m < 0) { /* is number negative? */ + buff[n++] = '-'; /* add signal */ + m = -m; /* make it positive */ + } + buff[n++] = '0'; buff[n++] = 'x'; /* add "0x" */ + m = adddigit(buff, n++, m * (1 << L_NBFD)); /* add first digit */ + e -= L_NBFD; /* this digit goes before the radix point */ + if (m > 0) { /* more digits? */ + buff[n++] = lua_getlocaledecpoint(); /* add radix point */ + do { /* add as many digits as needed */ + m = adddigit(buff, n++, m * 16); + } while (m > 0); + } + n += l_sprintf(buff + n, sz - n, "p%+d", e); /* add exponent */ + lua_assert(n < sz); + return n; + } +} + + +static int lua_number2strx (lua_State *L, char *buff, int sz, + const char *fmt, lua_Number x) { + int n = num2straux(buff, sz, x); + if (fmt[SIZELENMOD] == 'A') { + int i; + for (i = 0; i < n; i++) + buff[i] = toupper(uchar(buff[i])); + } + else if (fmt[SIZELENMOD] != 'a') + return luaL_error(L, "modifiers for format '%%a'/'%%A' not implemented"); + return n; +} + +#endif /* } */ + + +/* +** Maximum size of each formatted item. This maximum size is produced +** by format('%.99f', -maxfloat), and is equal to 99 + 3 ('-', '.', +** and '\0') + number of decimal digits to represent maxfloat (which +** is maximum exponent + 1). (99+3+1 then rounded to 120 for "extra +** expenses", such as locale-dependent stuff) +*/ +#define MAX_ITEM (120 + l_mathlim(MAX_10_EXP)) + + +/* valid flags in a format specification */ +#define FLAGS "-+ #0" + +/* +** maximum size of each format specification (such as "%-099.99d") +*/ +#define MAX_FORMAT 32 + + +static void addquoted (luaL_Buffer *b, const char *s, size_t len) { + luaL_addchar(b, '"'); + while (len--) { + if (*s == '"' || *s == '\\' || *s == '\n') { + luaL_addchar(b, '\\'); + luaL_addchar(b, *s); + } + else if (iscntrl(uchar(*s))) { + char buff[10]; + if (!isdigit(uchar(*(s+1)))) + l_sprintf(buff, sizeof(buff), "\\%d", (int)uchar(*s)); + else + l_sprintf(buff, sizeof(buff), "\\%03d", (int)uchar(*s)); + luaL_addstring(b, buff); + } + else + luaL_addchar(b, *s); + s++; + } + luaL_addchar(b, '"'); +} + + +/* +** Ensures the 'buff' string uses a dot as the radix character. +*/ +static void checkdp (char *buff, int nb) { + if (memchr(buff, '.', nb) == NULL) { /* no dot? */ + char point = lua_getlocaledecpoint(); /* try locale point */ + char *ppoint = (char *)memchr(buff, point, nb); + if (ppoint) *ppoint = '.'; /* change it to a dot */ + } +} + + +static void addliteral (lua_State *L, luaL_Buffer *b, int arg) { + switch (lua_type(L, arg)) { + case LUA_TSTRING: { + size_t len; + const char *s = lua_tolstring(L, arg, &len); + addquoted(b, s, len); + break; + } + case LUA_TNUMBER: { + char *buff = luaL_prepbuffsize(b, MAX_ITEM); + int nb; + if (!lua_isinteger(L, arg)) { /* float? */ + lua_Number n = lua_tonumber(L, arg); /* write as hexa ('%a') */ + nb = lua_number2strx(L, buff, MAX_ITEM, "%" LUA_NUMBER_FRMLEN "a", n); + checkdp(buff, nb); /* ensure it uses a dot */ + } + else { /* integers */ + lua_Integer n = lua_tointeger(L, arg); + const char *format = (n == LUA_MININTEGER) /* corner case? */ + ? "0x%" LUA_INTEGER_FRMLEN "x" /* use hexa */ + : LUA_INTEGER_FMT; /* else use default format */ + nb = l_sprintf(buff, MAX_ITEM, format, (LUAI_UACINT)n); + } + luaL_addsize(b, nb); + break; + } + case LUA_TNIL: case LUA_TBOOLEAN: { + luaL_tolstring(L, arg, NULL); + luaL_addvalue(b); + break; + } + default: { + luaL_argerror(L, arg, "value has no literal form"); + } + } +} + + +static const char *scanformat (lua_State *L, const char *strfrmt, char *form) { + const char *p = strfrmt; + while (*p != '\0' && strchr(FLAGS, *p) != NULL) p++; /* skip flags */ + if ((size_t)(p - strfrmt) >= sizeof(FLAGS)/sizeof(char)) + luaL_error(L, "invalid format (repeated flags)"); + if (isdigit(uchar(*p))) p++; /* skip width */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + if (*p == '.') { + p++; + if (isdigit(uchar(*p))) p++; /* skip precision */ + if (isdigit(uchar(*p))) p++; /* (2 digits at most) */ + } + if (isdigit(uchar(*p))) + luaL_error(L, "invalid format (width or precision too long)"); + *(form++) = '%'; + memcpy(form, strfrmt, ((p - strfrmt) + 1) * sizeof(char)); + form += (p - strfrmt) + 1; + *form = '\0'; + return p; +} + + +/* +** add length modifier into formats +*/ +static void addlenmod (char *form, const char *lenmod) { + size_t l = strlen(form); + size_t lm = strlen(lenmod); + char spec = form[l - 1]; + strcpy(form + l - 1, lenmod); + form[l + lm - 1] = spec; + form[l + lm] = '\0'; +} + + +static int str_format (lua_State *L) { + int top = lua_gettop(L); + int arg = 1; + size_t sfl; + const char *strfrmt = luaL_checklstring(L, arg, &sfl); + const char *strfrmt_end = strfrmt+sfl; + luaL_Buffer b; + luaL_buffinit(L, &b); + while (strfrmt < strfrmt_end) { + if (*strfrmt != L_ESC) + luaL_addchar(&b, *strfrmt++); + else if (*++strfrmt == L_ESC) + luaL_addchar(&b, *strfrmt++); /* %% */ + else { /* format item */ + char form[MAX_FORMAT]; /* to store the format ('%...') */ + char *buff = luaL_prepbuffsize(&b, MAX_ITEM); /* to put formatted item */ + int nb = 0; /* number of bytes in added item */ + if (++arg > top) + luaL_argerror(L, arg, "no value"); + strfrmt = scanformat(L, strfrmt, form); + switch (*strfrmt++) { + case 'c': { + nb = l_sprintf(buff, MAX_ITEM, form, (int)luaL_checkinteger(L, arg)); + break; + } + case 'd': case 'i': + case 'o': case 'u': case 'x': case 'X': { + lua_Integer n = luaL_checkinteger(L, arg); + addlenmod(form, LUA_INTEGER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACINT)n); + break; + } + case 'a': case 'A': + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = lua_number2strx(L, buff, MAX_ITEM, form, + luaL_checknumber(L, arg)); + break; + case 'e': case 'E': case 'f': + case 'g': case 'G': { + lua_Number n = luaL_checknumber(L, arg); + addlenmod(form, LUA_NUMBER_FRMLEN); + nb = l_sprintf(buff, MAX_ITEM, form, (LUAI_UACNUMBER)n); + break; + } + case 'q': { + addliteral(L, &b, arg); + break; + } + case 's': { + size_t l; + const char *s = luaL_tolstring(L, arg, &l); + if (form[2] == '\0') /* no modifiers? */ + luaL_addvalue(&b); /* keep entire string */ + else { + luaL_argcheck(L, l == strlen(s), arg, "string contains zeros"); + if (!strchr(form, '.') && l >= 100) { + /* no precision and string is too long to be formatted */ + luaL_addvalue(&b); /* keep entire string */ + } + else { /* format the string into 'buff' */ + nb = l_sprintf(buff, MAX_ITEM, form, s); + lua_pop(L, 1); /* remove result from 'luaL_tolstring' */ + } + } + break; + } + default: { /* also treat cases 'pnLlh' */ + return luaL_error(L, "invalid option '%%%c' to 'format'", + *(strfrmt - 1)); + } + } + lua_assert(nb < MAX_ITEM); + luaL_addsize(&b, nb); + } + } + luaL_pushresult(&b); + return 1; +} + +/* }====================================================== */ + + +/* +** {====================================================== +** PACK/UNPACK +** ======================================================= +*/ + + +/* value used for padding */ +#if !defined(LUAL_PACKPADBYTE) +#define LUAL_PACKPADBYTE 0x00 +#endif + +/* maximum size for the binary representation of an integer */ +#define MAXINTSIZE 16 + +/* number of bits in a character */ +#define NB CHAR_BIT + +/* mask for one character (NB 1's) */ +#define MC ((1 << NB) - 1) + +/* size of a lua_Integer */ +#define SZINT ((int)sizeof(lua_Integer)) + + +/* dummy union to get native endianness */ +static const union { + int dummy; + char little; /* true iff machine is little endian */ +} nativeendian = {1}; + + +/* dummy structure to get native alignment requirements */ +struct cD { + char c; + union { double d; void *p; lua_Integer i; lua_Number n; } u; +}; + +#define MAXALIGN (offsetof(struct cD, u)) + + +/* +** Union for serializing floats +*/ +typedef union Ftypes { + float f; + double d; + lua_Number n; + char buff[5 * sizeof(lua_Number)]; /* enough for any float type */ +} Ftypes; + + +/* +** information to pack/unpack stuff +*/ +typedef struct Header { + lua_State *L; + int islittle; + int maxalign; +} Header; + + +/* +** options for pack/unpack +*/ +typedef enum KOption { + Kint, /* signed integers */ + Kuint, /* unsigned integers */ + Kfloat, /* floating-point numbers */ + Kchar, /* fixed-length strings */ + Kstring, /* strings with prefixed length */ + Kzstr, /* zero-terminated strings */ + Kpadding, /* padding */ + Kpaddalign, /* padding for alignment */ + Knop /* no-op (configuration or spaces) */ +} KOption; + + +/* +** Read an integer numeral from string 'fmt' or return 'df' if +** there is no numeral +*/ +static int digit (int c) { return '0' <= c && c <= '9'; } + +static int getnum (const char **fmt, int df) { + if (!digit(**fmt)) /* no number? */ + return df; /* return default value */ + else { + int a = 0; + do { + a = a*10 + (*((*fmt)++) - '0'); + } while (digit(**fmt) && a <= ((int)MAXSIZE - 9)/10); + return a; + } +} + + +/* +** Read an integer numeral and raises an error if it is larger +** than the maximum size for integers. +*/ +static int getnumlimit (Header *h, const char **fmt, int df) { + int sz = getnum(fmt, df); + if (sz > MAXINTSIZE || sz <= 0) + return luaL_error(h->L, "integral size (%d) out of limits [1,%d]", + sz, MAXINTSIZE); + return sz; +} + + +/* +** Initialize Header +*/ +static void initheader (lua_State *L, Header *h) { + h->L = L; + h->islittle = nativeendian.little; + h->maxalign = 1; +} + + +/* +** Read and classify next option. 'size' is filled with option's size. +*/ +static KOption getoption (Header *h, const char **fmt, int *size) { + int opt = *((*fmt)++); + *size = 0; /* default */ + switch (opt) { + case 'b': *size = sizeof(char); return Kint; + case 'B': *size = sizeof(char); return Kuint; + case 'h': *size = sizeof(short); return Kint; + case 'H': *size = sizeof(short); return Kuint; + case 'l': *size = sizeof(long); return Kint; + case 'L': *size = sizeof(long); return Kuint; + case 'j': *size = sizeof(lua_Integer); return Kint; + case 'J': *size = sizeof(lua_Integer); return Kuint; + case 'T': *size = sizeof(size_t); return Kuint; + case 'f': *size = sizeof(float); return Kfloat; + case 'd': *size = sizeof(double); return Kfloat; + case 'n': *size = sizeof(lua_Number); return Kfloat; + case 'i': *size = getnumlimit(h, fmt, sizeof(int)); return Kint; + case 'I': *size = getnumlimit(h, fmt, sizeof(int)); return Kuint; + case 's': *size = getnumlimit(h, fmt, sizeof(size_t)); return Kstring; + case 'c': + *size = getnum(fmt, -1); + if (*size == -1) + luaL_error(h->L, "missing size for format option 'c'"); + return Kchar; + case 'z': return Kzstr; + case 'x': *size = 1; return Kpadding; + case 'X': return Kpaddalign; + case ' ': break; + case '<': h->islittle = 1; break; + case '>': h->islittle = 0; break; + case '=': h->islittle = nativeendian.little; break; + case '!': h->maxalign = getnumlimit(h, fmt, MAXALIGN); break; + default: luaL_error(h->L, "invalid format option '%c'", opt); + } + return Knop; +} + + +/* +** Read, classify, and fill other details about the next option. +** 'psize' is filled with option's size, 'notoalign' with its +** alignment requirements. +** Local variable 'size' gets the size to be aligned. (Kpadal option +** always gets its full alignment, other options are limited by +** the maximum alignment ('maxalign'). Kchar option needs no alignment +** despite its size. +*/ +static KOption getdetails (Header *h, size_t totalsize, + const char **fmt, int *psize, int *ntoalign) { + KOption opt = getoption(h, fmt, psize); + int align = *psize; /* usually, alignment follows size */ + if (opt == Kpaddalign) { /* 'X' gets alignment from following option */ + if (**fmt == '\0' || getoption(h, fmt, &align) == Kchar || align == 0) + luaL_argerror(h->L, 1, "invalid next option for option 'X'"); + } + if (align <= 1 || opt == Kchar) /* need no alignment? */ + *ntoalign = 0; + else { + if (align > h->maxalign) /* enforce maximum alignment */ + align = h->maxalign; + if ((align & (align - 1)) != 0) /* is 'align' not a power of 2? */ + luaL_argerror(h->L, 1, "format asks for alignment not power of 2"); + *ntoalign = (align - (int)(totalsize & (align - 1))) & (align - 1); + } + return opt; +} + + +/* +** Pack integer 'n' with 'size' bytes and 'islittle' endianness. +** The final 'if' handles the case when 'size' is larger than +** the size of a Lua integer, correcting the extra sign-extension +** bytes if necessary (by default they would be zeros). +*/ +static void packint (luaL_Buffer *b, lua_Unsigned n, + int islittle, int size, int neg) { + char *buff = luaL_prepbuffsize(b, size); + int i; + buff[islittle ? 0 : size - 1] = (char)(n & MC); /* first byte */ + for (i = 1; i < size; i++) { + n >>= NB; + buff[islittle ? i : size - 1 - i] = (char)(n & MC); + } + if (neg && size > SZINT) { /* negative number need sign extension? */ + for (i = SZINT; i < size; i++) /* correct extra bytes */ + buff[islittle ? i : size - 1 - i] = (char)MC; + } + luaL_addsize(b, size); /* add result to buffer */ +} + + +/* +** Copy 'size' bytes from 'src' to 'dest', correcting endianness if +** given 'islittle' is different from native endianness. +*/ +static void copywithendian (volatile char *dest, volatile const char *src, + int size, int islittle) { + if (islittle == nativeendian.little) { + while (size-- != 0) + *(dest++) = *(src++); + } + else { + dest += size - 1; + while (size-- != 0) + *(dest--) = *(src++); + } +} + + +static int str_pack (lua_State *L) { + luaL_Buffer b; + Header h; + const char *fmt = luaL_checkstring(L, 1); /* format string */ + int arg = 1; /* current argument to pack */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + lua_pushnil(L); /* mark to separate arguments from string buffer */ + luaL_buffinit(L, &b); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + totalsize += ntoalign + size; + while (ntoalign-- > 0) + luaL_addchar(&b, LUAL_PACKPADBYTE); /* fill alignment */ + arg++; + switch (opt) { + case Kint: { /* signed integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) { /* need overflow check? */ + lua_Integer lim = (lua_Integer)1 << ((size * NB) - 1); + luaL_argcheck(L, -lim <= n && n < lim, arg, "integer overflow"); + } + packint(&b, (lua_Unsigned)n, h.islittle, size, (n < 0)); + break; + } + case Kuint: { /* unsigned integers */ + lua_Integer n = luaL_checkinteger(L, arg); + if (size < SZINT) /* need overflow check? */ + luaL_argcheck(L, (lua_Unsigned)n < ((lua_Unsigned)1 << (size * NB)), + arg, "unsigned overflow"); + packint(&b, (lua_Unsigned)n, h.islittle, size, 0); + break; + } + case Kfloat: { /* floating-point options */ + volatile Ftypes u; + char *buff = luaL_prepbuffsize(&b, size); + lua_Number n = luaL_checknumber(L, arg); /* get argument */ + if (size == sizeof(u.f)) u.f = (float)n; /* copy it into 'u' */ + else if (size == sizeof(u.d)) u.d = (double)n; + else u.n = n; + /* move 'u' to final result, correcting endianness if needed */ + copywithendian(buff, u.buff, size, h.islittle); + luaL_addsize(&b, size); + break; + } + case Kchar: { /* fixed-size string */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, len <= (size_t)size, arg, + "string longer than given size"); + luaL_addlstring(&b, s, len); /* add string */ + while (len++ < (size_t)size) /* pad extra space */ + luaL_addchar(&b, LUAL_PACKPADBYTE); + break; + } + case Kstring: { /* strings with length count */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, size >= (int)sizeof(size_t) || + len < ((size_t)1 << (size * NB)), + arg, "string length does not fit in given size"); + packint(&b, (lua_Unsigned)len, h.islittle, size, 0); /* pack length */ + luaL_addlstring(&b, s, len); + totalsize += len; + break; + } + case Kzstr: { /* zero-terminated string */ + size_t len; + const char *s = luaL_checklstring(L, arg, &len); + luaL_argcheck(L, strlen(s) == len, arg, "string contains zeros"); + luaL_addlstring(&b, s, len); + luaL_addchar(&b, '\0'); /* add zero at the end */ + totalsize += len + 1; + break; + } + case Kpadding: luaL_addchar(&b, LUAL_PACKPADBYTE); /* FALLTHROUGH */ + case Kpaddalign: case Knop: + arg--; /* undo increment */ + break; + } + } + luaL_pushresult(&b); + return 1; +} + + +static int str_packsize (lua_State *L) { + Header h; + const char *fmt = luaL_checkstring(L, 1); /* format string */ + size_t totalsize = 0; /* accumulate total size of result */ + initheader(L, &h); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, totalsize, &fmt, &size, &ntoalign); + size += ntoalign; /* total space used by option */ + luaL_argcheck(L, totalsize <= MAXSIZE - size, 1, + "format result too large"); + totalsize += size; + switch (opt) { + case Kstring: /* strings with length count */ + case Kzstr: /* zero-terminated string */ + luaL_argerror(L, 1, "variable-length format"); + /* call never return, but to avoid warnings: *//* FALLTHROUGH */ + default: break; + } + } + lua_pushinteger(L, (lua_Integer)totalsize); + return 1; +} + + +/* +** Unpack an integer with 'size' bytes and 'islittle' endianness. +** If size is smaller than the size of a Lua integer and integer +** is signed, must do sign extension (propagating the sign to the +** higher bits); if size is larger than the size of a Lua integer, +** it must check the unread bytes to see whether they do not cause an +** overflow. +*/ +static lua_Integer unpackint (lua_State *L, const char *str, + int islittle, int size, int issigned) { + lua_Unsigned res = 0; + int i; + int limit = (size <= SZINT) ? size : SZINT; + for (i = limit - 1; i >= 0; i--) { + res <<= NB; + res |= (lua_Unsigned)(unsigned char)str[islittle ? i : size - 1 - i]; + } + if (size < SZINT) { /* real size smaller than lua_Integer? */ + if (issigned) { /* needs sign extension? */ + lua_Unsigned mask = (lua_Unsigned)1 << (size*NB - 1); + res = ((res ^ mask) - mask); /* do sign extension */ + } + } + else if (size > SZINT) { /* must check unread bytes */ + int mask = (!issigned || (lua_Integer)res >= 0) ? 0 : MC; + for (i = limit; i < size; i++) { + if ((unsigned char)str[islittle ? i : size - 1 - i] != mask) + luaL_error(L, "%d-byte integer does not fit into Lua Integer", size); + } + } + return (lua_Integer)res; +} + + +static int str_unpack (lua_State *L) { + Header h; + const char *fmt = luaL_checkstring(L, 1); + size_t ld; + const char *data = luaL_checklstring(L, 2, &ld); + size_t pos = (size_t)posrelat(luaL_optinteger(L, 3, 1), ld) - 1; + int n = 0; /* number of results */ + luaL_argcheck(L, pos <= ld, 3, "initial position out of string"); + initheader(L, &h); + while (*fmt != '\0') { + int size, ntoalign; + KOption opt = getdetails(&h, pos, &fmt, &size, &ntoalign); + if ((size_t)ntoalign + size > ~pos || pos + ntoalign + size > ld) + luaL_argerror(L, 2, "data string too short"); + pos += ntoalign; /* skip alignment */ + /* stack space for item + next position */ + luaL_checkstack(L, 2, "too many results"); + n++; + switch (opt) { + case Kint: + case Kuint: { + lua_Integer res = unpackint(L, data + pos, h.islittle, size, + (opt == Kint)); + lua_pushinteger(L, res); + break; + } + case Kfloat: { + volatile Ftypes u; + lua_Number num; + copywithendian(u.buff, data + pos, size, h.islittle); + if (size == sizeof(u.f)) num = (lua_Number)u.f; + else if (size == sizeof(u.d)) num = (lua_Number)u.d; + else num = u.n; + lua_pushnumber(L, num); + break; + } + case Kchar: { + lua_pushlstring(L, data + pos, size); + break; + } + case Kstring: { + size_t len = (size_t)unpackint(L, data + pos, h.islittle, size, 0); + luaL_argcheck(L, pos + len + size <= ld, 2, "data string too short"); + lua_pushlstring(L, data + pos + size, len); + pos += len; /* skip string */ + break; + } + case Kzstr: { + size_t len = (int)strlen(data + pos); + lua_pushlstring(L, data + pos, len); + pos += len + 1; /* skip string plus final '\0' */ + break; + } + case Kpaddalign: case Kpadding: case Knop: + n--; /* undo increment */ + break; + } + pos += size; + } + lua_pushinteger(L, pos + 1); /* next position */ + return n + 1; +} + +/* }====================================================== */ + + +static const luaL_Reg strlib[] = { + {"byte", str_byte}, + {"char", str_char}, + {"dump", str_dump}, + {"find", str_find}, + {"format", str_format}, + {"gmatch", gmatch}, + {"gsub", str_gsub}, + {"len", str_len}, + {"lower", str_lower}, + {"match", str_match}, + {"rep", str_rep}, + {"reverse", str_reverse}, + {"sub", str_sub}, + {"upper", str_upper}, + {"pack", str_pack}, + {"packsize", str_packsize}, + {"unpack", str_unpack}, + {NULL, NULL} +}; + + +static void createmetatable (lua_State *L) { + lua_createtable(L, 0, 1); /* table to be metatable for strings */ + lua_pushliteral(L, ""); /* dummy string */ + lua_pushvalue(L, -2); /* copy table */ + lua_setmetatable(L, -2); /* set table as metatable for strings */ + lua_pop(L, 1); /* pop dummy string */ + lua_pushvalue(L, -2); /* get string library */ + lua_setfield(L, -2, "__index"); /* metatable.__index = string */ + lua_pop(L, 1); /* pop metatable */ +} + + +/* +** Open string library +*/ +LUAMOD_API int luaopen_string (lua_State *L) { + luaL_newlib(L, strlib); + createmetatable(L); + return 1; +} + diff --git a/src/lua/ltable.c b/src/lua/ltable.c new file mode 100644 index 000000000000..ea4fe7fcb313 --- /dev/null +++ b/src/lua/ltable.c @@ -0,0 +1,688 @@ +/* +** $Id: ltable.c,v 2.118.1.4 2018/06/08 16:22:51 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#define ltable_c +#define LUA_CORE + +#include "lprefix.h" + + +/* +** Implementation of tables (aka arrays, objects, or hash tables). +** Tables keep its elements in two parts: an array part and a hash part. +** Non-negative integer keys are all candidates to be kept in the array +** part. The actual size of the array is the largest 'n' such that +** more than half the slots between 1 and n are in use. +** Hash uses a mix of chained scatter table with Brent's variation. +** A main invariant of these tables is that, if an element is not +** in its main position (i.e. the 'original' position that its hash gives +** to it), then the colliding element is in its own main position. +** Hence even when the load factor reaches 100%, performance remains good. +*/ + +#include +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lgc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "lvm.h" + + +/* +** Maximum size of array part (MAXASIZE) is 2^MAXABITS. MAXABITS is +** the largest integer such that MAXASIZE fits in an unsigned int. +*/ +#define MAXABITS cast_int(sizeof(int) * CHAR_BIT - 1) +#define MAXASIZE (1u << MAXABITS) + +/* +** Maximum size of hash part is 2^MAXHBITS. MAXHBITS is the largest +** integer such that 2^MAXHBITS fits in a signed int. (Note that the +** maximum number of elements in a table, 2^MAXABITS + 2^MAXHBITS, still +** fits comfortably in an unsigned int.) +*/ +#define MAXHBITS (MAXABITS - 1) + + +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) + +#define hashstr(t,str) hashpow2(t, (str)->hash) +#define hashboolean(t,p) hashpow2(t, p) +#define hashint(t,i) hashpow2(t, i) + + +/* +** for some types, it is better to avoid modulus by power of 2, as +** they tend to have many 2 factors. +*/ +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) + + +#define hashpointer(t,p) hashmod(t, point2uint(p)) + + +#define dummynode (&dummynode_) + +static const Node dummynode_ = { + {NILCONSTANT}, /* value */ + {{NILCONSTANT, 0}} /* key */ +}; + + +/* +** Hash for floating-point numbers. +** The main computation should be just +** n = frexp(n, &i); return (n * INT_MAX) + i +** but there are some numerical subtleties. +** In a two-complement representation, INT_MAX does not has an exact +** representation as a float, but INT_MIN does; because the absolute +** value of 'frexp' is smaller than 1 (unless 'n' is inf/NaN), the +** absolute value of the product 'frexp * -INT_MIN' is smaller or equal +** to INT_MAX. Next, the use of 'unsigned int' avoids overflows when +** adding 'i'; the use of '~u' (instead of '-u') avoids problems with +** INT_MIN. +*/ +#if !defined(l_hashfloat) +static int l_hashfloat (lua_Number n) { + int i; + lua_Integer ni; + n = l_mathop(frexp)(n, &i) * -cast_num(INT_MIN); + if (!lua_numbertointeger(n, &ni)) { /* is 'n' inf/-inf/NaN? */ + lua_assert(luai_numisnan(n) || l_mathop(fabs)(n) == cast_num(HUGE_VAL)); + return 0; + } + else { /* normal case */ + unsigned int u = cast(unsigned int, i) + cast(unsigned int, ni); + return cast_int(u <= cast(unsigned int, INT_MAX) ? u : ~u); + } +} +#endif + + +/* +** returns the 'main' position of an element in a table (that is, the index +** of its hash value) +*/ +static Node *mainposition (const Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TNUMINT: + return hashint(t, ivalue(key)); + case LUA_TNUMFLT: + return hashmod(t, l_hashfloat(fltvalue(key))); + case LUA_TSHRSTR: + return hashstr(t, tsvalue(key)); + case LUA_TLNGSTR: + return hashpow2(t, luaS_hashlongstr(tsvalue(key))); + case LUA_TBOOLEAN: + return hashboolean(t, bvalue(key)); + case LUA_TLIGHTUSERDATA: + return hashpointer(t, pvalue(key)); + case LUA_TLCF: + return hashpointer(t, fvalue(key)); + default: + lua_assert(!ttisdeadkey(key)); + return hashpointer(t, gcvalue(key)); + } +} + + +/* +** returns the index for 'key' if 'key' is an appropriate key to live in +** the array part of the table, 0 otherwise. +*/ +static unsigned int arrayindex (const TValue *key) { + if (ttisinteger(key)) { + lua_Integer k = ivalue(key); + if (0 < k && (lua_Unsigned)k <= MAXASIZE) + return cast(unsigned int, k); /* 'key' is an appropriate array index */ + } + return 0; /* 'key' did not match some condition */ +} + + +/* +** returns the index of a 'key' for table traversals. First goes all +** elements in the array part, then elements in the hash part. The +** beginning of a traversal is signaled by 0. +*/ +static unsigned int findindex (lua_State *L, Table *t, StkId key) { + unsigned int i; + if (ttisnil(key)) return 0; /* first iteration */ + i = arrayindex(key); + if (i != 0 && i <= t->sizearray) /* is 'key' inside array part? */ + return i; /* yes; that's the index */ + else { + int nx; + Node *n = mainposition(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + /* key may be dead already, but it is ok to use it in 'next' */ + if (luaV_rawequalobj(gkey(n), key) || + (ttisdeadkey(gkey(n)) && iscollectable(key) && + deadvalue(gkey(n)) == gcvalue(key))) { + i = cast_int(n - gnode(t, 0)); /* key index in hash table */ + /* hash elements are numbered after array ones */ + return (i + 1) + t->sizearray; + } + nx = gnext(n); + if (nx == 0) + luaG_runerror(L, "invalid key to 'next'"); /* key not found */ + else n += nx; + } + } +} + + +int luaH_next (lua_State *L, Table *t, StkId key) { + unsigned int i = findindex(L, t, key); /* find original element */ + for (; i < t->sizearray; i++) { /* try first array part */ + if (!ttisnil(&t->array[i])) { /* a non-nil value? */ + setivalue(key, i + 1); + setobj2s(L, key+1, &t->array[i]); + return 1; + } + } + for (i -= t->sizearray; cast_int(i) < sizenode(t); i++) { /* hash part */ + if (!ttisnil(gval(gnode(t, i)))) { /* a non-nil value? */ + setobj2s(L, key, gkey(gnode(t, i))); + setobj2s(L, key+1, gval(gnode(t, i))); + return 1; + } + } + return 0; /* no more elements */ +} + + +/* +** {============================================================= +** Rehash +** ============================================================== +*/ + +/* +** Compute the optimal size for the array part of table 't'. 'nums' is a +** "count array" where 'nums[i]' is the number of integers in the table +** between 2^(i - 1) + 1 and 2^i. 'pna' enters with the total number of +** integer keys in the table and leaves with the number of keys that +** will go to the array part; return the optimal size. +*/ +static unsigned int computesizes (unsigned int nums[], unsigned int *pna) { + int i; + unsigned int twotoi; /* 2^i (candidate for optimal size) */ + unsigned int a = 0; /* number of elements smaller than 2^i */ + unsigned int na = 0; /* number of elements to go to array part */ + unsigned int optimal = 0; /* optimal size for array part */ + /* loop while keys can fill more than half of total size */ + for (i = 0, twotoi = 1; + twotoi > 0 && *pna > twotoi / 2; + i++, twotoi *= 2) { + if (nums[i] > 0) { + a += nums[i]; + if (a > twotoi/2) { /* more than half elements present? */ + optimal = twotoi; /* optimal size (till now) */ + na = a; /* all elements up to 'optimal' will go to array part */ + } + } + } + lua_assert((optimal == 0 || optimal / 2 < na) && na <= optimal); + *pna = na; + return optimal; +} + + +static int countint (const TValue *key, unsigned int *nums) { + unsigned int k = arrayindex(key); + if (k != 0) { /* is 'key' an appropriate array index? */ + nums[luaO_ceillog2(k)]++; /* count as such */ + return 1; + } + else + return 0; +} + + +/* +** Count keys in array part of table 't': Fill 'nums[i]' with +** number of keys that will go into corresponding slice and return +** total number of non-nil keys. +*/ +static unsigned int numusearray (const Table *t, unsigned int *nums) { + int lg; + unsigned int ttlg; /* 2^lg */ + unsigned int ause = 0; /* summation of 'nums' */ + unsigned int i = 1; /* count to traverse all array keys */ + /* traverse each slice */ + for (lg = 0, ttlg = 1; lg <= MAXABITS; lg++, ttlg *= 2) { + unsigned int lc = 0; /* counter */ + unsigned int lim = ttlg; + if (lim > t->sizearray) { + lim = t->sizearray; /* adjust upper limit */ + if (i > lim) + break; /* no more elements to count */ + } + /* count elements in range (2^(lg - 1), 2^lg] */ + for (; i <= lim; i++) { + if (!ttisnil(&t->array[i-1])) + lc++; + } + nums[lg] += lc; + ause += lc; + } + return ause; +} + + +static int numusehash (const Table *t, unsigned int *nums, unsigned int *pna) { + int totaluse = 0; /* total number of elements */ + int ause = 0; /* elements added to 'nums' (can go to array part) */ + int i = sizenode(t); + while (i--) { + Node *n = &t->node[i]; + if (!ttisnil(gval(n))) { + ause += countint(gkey(n), nums); + totaluse++; + } + } + *pna += ause; + return totaluse; +} + + +static void setarrayvector (lua_State *L, Table *t, unsigned int size) { + unsigned int i; + luaM_reallocvector(L, t->array, t->sizearray, size, TValue); + for (i=t->sizearray; iarray[i]); + t->sizearray = size; +} + + +static void setnodevector (lua_State *L, Table *t, unsigned int size) { + if (size == 0) { /* no elements to hash part? */ + t->node = cast(Node *, dummynode); /* use common 'dummynode' */ + t->lsizenode = 0; + t->lastfree = NULL; /* signal that it is using dummy node */ + } + else { + int i; + int lsize = luaO_ceillog2(size); + if (lsize > MAXHBITS) + luaG_runerror(L, "table overflow"); + size = twoto(lsize); + t->node = luaM_newvector(L, size, Node); + for (i = 0; i < (int)size; i++) { + Node *n = gnode(t, i); + gnext(n) = 0; + setnilvalue(wgkey(n)); + setnilvalue(gval(n)); + } + t->lsizenode = cast_byte(lsize); + t->lastfree = gnode(t, size); /* all positions are free */ + } +} + + +typedef struct { + Table *t; + unsigned int nhsize; +} AuxsetnodeT; + + +static void auxsetnode (lua_State *L, void *ud) { + AuxsetnodeT *asn = cast(AuxsetnodeT *, ud); + setnodevector(L, asn->t, asn->nhsize); +} + + +void luaH_resize (lua_State *L, Table *t, unsigned int nasize, + unsigned int nhsize) { + unsigned int i; + int j; + AuxsetnodeT asn; + unsigned int oldasize = t->sizearray; + int oldhsize = allocsizenode(t); + Node *nold = t->node; /* save old hash ... */ + if (nasize > oldasize) /* array part must grow? */ + setarrayvector(L, t, nasize); + /* create new hash part with appropriate size */ + asn.t = t; asn.nhsize = nhsize; + if (luaD_rawrunprotected(L, auxsetnode, &asn) != LUA_OK) { /* mem. error? */ + setarrayvector(L, t, oldasize); /* array back to its original size */ + luaD_throw(L, LUA_ERRMEM); /* rethrow memory error */ + } + if (nasize < oldasize) { /* array part must shrink? */ + t->sizearray = nasize; + /* re-insert elements from vanishing slice */ + for (i=nasize; iarray[i])) + luaH_setint(L, t, i + 1, &t->array[i]); + } + /* shrink array */ + luaM_reallocvector(L, t->array, oldasize, nasize, TValue); + } + /* re-insert elements from hash part */ + for (j = oldhsize - 1; j >= 0; j--) { + Node *old = nold + j; + if (!ttisnil(gval(old))) { + /* doesn't need barrier/invalidate cache, as entry was + already present in the table */ + setobjt2t(L, luaH_set(L, t, gkey(old)), gval(old)); + } + } + if (oldhsize > 0) /* not the dummy node? */ + luaM_freearray(L, nold, cast(size_t, oldhsize)); /* free old hash */ +} + + +void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize) { + int nsize = allocsizenode(t); + luaH_resize(L, t, nasize, nsize); +} + +/* +** nums[i] = number of keys 'k' where 2^(i - 1) < k <= 2^i +*/ +static void rehash (lua_State *L, Table *t, const TValue *ek) { + unsigned int asize; /* optimal size for array part */ + unsigned int na; /* number of keys in the array part */ + unsigned int nums[MAXABITS + 1]; + int i; + int totaluse; + for (i = 0; i <= MAXABITS; i++) nums[i] = 0; /* reset counts */ + na = numusearray(t, nums); /* count keys in array part */ + totaluse = na; /* all those keys are integer keys */ + totaluse += numusehash(t, nums, &na); /* count keys in hash part */ + /* count extra key */ + na += countint(ek, nums); + totaluse++; + /* compute new size for array part */ + asize = computesizes(nums, &na); + /* resize the table to new computed sizes */ + luaH_resize(L, t, asize, totaluse - na); +} + + + +/* +** }============================================================= +*/ + + +Table *luaH_new (lua_State *L) { + GCObject *o = luaC_newobj(L, LUA_TTABLE, sizeof(Table)); + Table *t = gco2t(o); + t->metatable = NULL; + t->flags = cast_byte(~0); + t->array = NULL; + t->sizearray = 0; + setnodevector(L, t, 0); + return t; +} + + +void luaH_free (lua_State *L, Table *t) { + if (!isdummy(t)) + luaM_freearray(L, t->node, cast(size_t, sizenode(t))); + luaM_freearray(L, t->array, t->sizearray); + luaM_free(L, t); +} + + +static Node *getfreepos (Table *t) { + if (!isdummy(t)) { + while (t->lastfree > t->node) { + t->lastfree--; + if (ttisnil(gkey(t->lastfree))) + return t->lastfree; + } + } + return NULL; /* could not find a free place */ +} + + + +/* +** inserts a new key into a hash table; first, check whether key's main +** position is free. If not, check whether colliding node is in its main +** position or not: if it is not, move colliding node to an empty place and +** put new key in its main position; otherwise (colliding node is in its main +** position), new key goes to an empty position. +*/ +TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key) { + Node *mp; + TValue aux; + if (ttisnil(key)) luaG_runerror(L, "table index is nil"); + else if (ttisfloat(key)) { + lua_Integer k; + if (luaV_tointeger(key, &k, 0)) { /* does index fit in an integer? */ + setivalue(&aux, k); + key = &aux; /* insert it as an integer */ + } + else if (luai_numisnan(fltvalue(key))) + luaG_runerror(L, "table index is NaN"); + } + mp = mainposition(t, key); + if (!ttisnil(gval(mp)) || isdummy(t)) { /* main position is taken? */ + Node *othern; + Node *f = getfreepos(t); /* get a free place */ + if (f == NULL) { /* cannot find a free place? */ + rehash(L, t, key); /* grow table */ + /* whatever called 'newkey' takes care of TM cache */ + return luaH_set(L, t, key); /* insert key into grown table */ + } + lua_assert(!isdummy(t)); + othern = mainposition(t, gkey(mp)); + if (othern != mp) { /* is colliding node out of its main position? */ + /* yes; move colliding node into free position */ + while (othern + gnext(othern) != mp) /* find previous */ + othern += gnext(othern); + gnext(othern) = cast_int(f - othern); /* rechain to point to 'f' */ + *f = *mp; /* copy colliding node into free pos. (mp->next also goes) */ + if (gnext(mp) != 0) { + gnext(f) += cast_int(mp - f); /* correct 'next' */ + gnext(mp) = 0; /* now 'mp' is free */ + } + setnilvalue(gval(mp)); + } + else { /* colliding node is in its own main position */ + /* new node will go into free position */ + if (gnext(mp) != 0) + gnext(f) = cast_int((mp + gnext(mp)) - f); /* chain new position */ + else lua_assert(gnext(f) == 0); + gnext(mp) = cast_int(f - mp); + mp = f; + } + } + setnodekey(L, &mp->i_key, key); + luaC_barrierback(L, t, key); + lua_assert(ttisnil(gval(mp))); + return gval(mp); +} + + +/* +** search function for integers +*/ +const TValue *luaH_getint (Table *t, lua_Integer key) { + /* (1 <= key && key <= t->sizearray) */ + if (l_castS2U(key) - 1 < t->sizearray) + return &t->array[key - 1]; + else { + Node *n = hashint(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (ttisinteger(gkey(n)) && ivalue(gkey(n)) == key) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) break; + n += nx; + } + } + return luaO_nilobject; + } +} + + +/* +** search function for short strings +*/ +const TValue *luaH_getshortstr (Table *t, TString *key) { + Node *n = hashstr(t, key); + lua_assert(key->tt == LUA_TSHRSTR); + for (;;) { /* check whether 'key' is somewhere in the chain */ + const TValue *k = gkey(n); + if (ttisshrstring(k) && eqshrstr(tsvalue(k), key)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } +} + + +/* +** "Generic" get version. (Not that generic: not valid for integers, +** which may be in array part, nor for floats with integral values.) +*/ +static const TValue *getgeneric (Table *t, const TValue *key) { + Node *n = mainposition(t, key); + for (;;) { /* check whether 'key' is somewhere in the chain */ + if (luaV_rawequalobj(gkey(n), key)) + return gval(n); /* that's it */ + else { + int nx = gnext(n); + if (nx == 0) + return luaO_nilobject; /* not found */ + n += nx; + } + } +} + + +const TValue *luaH_getstr (Table *t, TString *key) { + if (key->tt == LUA_TSHRSTR) + return luaH_getshortstr(t, key); + else { /* for long strings, use generic case */ + TValue ko; + setsvalue(cast(lua_State *, NULL), &ko, key); + return getgeneric(t, &ko); + } +} + + +/* +** main search function +*/ +const TValue *luaH_get (Table *t, const TValue *key) { + switch (ttype(key)) { + case LUA_TSHRSTR: return luaH_getshortstr(t, tsvalue(key)); + case LUA_TNUMINT: return luaH_getint(t, ivalue(key)); + case LUA_TNIL: return luaO_nilobject; + case LUA_TNUMFLT: { + lua_Integer k; + if (luaV_tointeger(key, &k, 0)) /* index is int? */ + return luaH_getint(t, k); /* use specialized version */ + /* else... */ + } /* FALLTHROUGH */ + default: + return getgeneric(t, key); + } +} + + +/* +** beware: when using this function you probably need to check a GC +** barrier and invalidate the TM cache. +*/ +TValue *luaH_set (lua_State *L, Table *t, const TValue *key) { + const TValue *p = luaH_get(t, key); + if (p != luaO_nilobject) + return cast(TValue *, p); + else return luaH_newkey(L, t, key); +} + + +void luaH_setint (lua_State *L, Table *t, lua_Integer key, TValue *value) { + const TValue *p = luaH_getint(t, key); + TValue *cell; + if (p != luaO_nilobject) + cell = cast(TValue *, p); + else { + TValue k; + setivalue(&k, key); + cell = luaH_newkey(L, t, &k); + } + setobj2t(L, cell, value); +} + + +static lua_Unsigned unbound_search (Table *t, lua_Unsigned j) { + lua_Unsigned i = j; /* i is zero or a present index */ + j++; + /* find 'i' and 'j' such that i is present and j is not */ + while (!ttisnil(luaH_getint(t, j))) { + i = j; + if (j > l_castS2U(LUA_MAXINTEGER) / 2) { /* overflow? */ + /* table was built with bad purposes: resort to linear search */ + i = 1; + while (!ttisnil(luaH_getint(t, i))) i++; + return i - 1; + } + j *= 2; + } + /* now do a binary search between them */ + while (j - i > 1) { + lua_Unsigned m = (i+j)/2; + if (ttisnil(luaH_getint(t, m))) j = m; + else i = m; + } + return i; +} + + +/* +** Try to find a boundary in table 't'. A 'boundary' is an integer index +** such that t[i] is non-nil and t[i+1] is nil (and 0 if t[1] is nil). +*/ +lua_Unsigned luaH_getn (Table *t) { + unsigned int j = t->sizearray; + if (j > 0 && ttisnil(&t->array[j - 1])) { + /* there is a boundary in the array part: (binary) search for it */ + unsigned int i = 0; + while (j - i > 1) { + unsigned int m = (i+j)/2; + if (ttisnil(&t->array[m - 1])) j = m; + else i = m; + } + return i; + } + /* else must find a boundary in hash part */ + else if (isdummy(t)) /* hash part is empty? */ + return j; /* that is easy... */ + else return unbound_search(t, j); +} + + + +#if defined(LUA_DEBUG) + +Node *luaH_mainposition (const Table *t, const TValue *key) { + return mainposition(t, key); +} + +int luaH_isdummy (const Table *t) { return isdummy(t); } + +#endif diff --git a/src/lua/ltable.h b/src/lua/ltable.h new file mode 100644 index 000000000000..92db0ac7bf18 --- /dev/null +++ b/src/lua/ltable.h @@ -0,0 +1,66 @@ +/* +** $Id: ltable.h,v 2.23.1.2 2018/05/24 19:39:05 roberto Exp $ +** Lua tables (hash) +** See Copyright Notice in lua.h +*/ + +#ifndef ltable_h +#define ltable_h + +#include "lobject.h" + + +#define gnode(t,i) (&(t)->node[i]) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) + + +/* 'const' to avoid wrong writings that can mess up field 'next' */ +#define gkey(n) cast(const TValue*, (&(n)->i_key.tvk)) + +/* +** writable version of 'gkey'; allows updates to individual fields, +** but not to the whole (which has incompatible type) +*/ +#define wgkey(n) (&(n)->i_key.nk) + +#define invalidateTMcache(t) ((t)->flags = 0) + + +/* true when 't' is using 'dummynode' as its hash part */ +#define isdummy(t) ((t)->lastfree == NULL) + + +/* allocated size for hash nodes */ +#define allocsizenode(t) (isdummy(t) ? 0 : sizenode(t)) + + +/* returns the key, given the value of a table entry */ +#define keyfromval(v) \ + (gkey(cast(Node *, cast(char *, (v)) - offsetof(Node, i_val)))) + + +LUAI_FUNC const TValue *luaH_getint (Table *t, lua_Integer key); +LUAI_FUNC void luaH_setint (lua_State *L, Table *t, lua_Integer key, + TValue *value); +LUAI_FUNC const TValue *luaH_getshortstr (Table *t, TString *key); +LUAI_FUNC const TValue *luaH_getstr (Table *t, TString *key); +LUAI_FUNC const TValue *luaH_get (Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_newkey (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC TValue *luaH_set (lua_State *L, Table *t, const TValue *key); +LUAI_FUNC Table *luaH_new (lua_State *L); +LUAI_FUNC void luaH_resize (lua_State *L, Table *t, unsigned int nasize, + unsigned int nhsize); +LUAI_FUNC void luaH_resizearray (lua_State *L, Table *t, unsigned int nasize); +LUAI_FUNC void luaH_free (lua_State *L, Table *t); +LUAI_FUNC int luaH_next (lua_State *L, Table *t, StkId key); +LUAI_FUNC lua_Unsigned luaH_getn (Table *t); + + +#if defined(LUA_DEBUG) +LUAI_FUNC Node *luaH_mainposition (const Table *t, const TValue *key); +LUAI_FUNC int luaH_isdummy (const Table *t); +#endif + + +#endif diff --git a/src/lua/ltablib.c b/src/lua/ltablib.c new file mode 100644 index 000000000000..c5349578ec7f --- /dev/null +++ b/src/lua/ltablib.c @@ -0,0 +1,450 @@ +/* +** $Id: ltablib.c,v 1.93.1.1 2017/04/19 17:20:42 roberto Exp $ +** Library for Table Manipulation +** See Copyright Notice in lua.h +*/ + +#define ltablib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + + +/* +** Operations that an object must define to mimic a table +** (some functions only need some of them) +*/ +#define TAB_R 1 /* read */ +#define TAB_W 2 /* write */ +#define TAB_L 4 /* length */ +#define TAB_RW (TAB_R | TAB_W) /* read/write */ + + +#define aux_getn(L,n,w) (checktab(L, n, (w) | TAB_L), luaL_len(L, n)) + + +static int checkfield (lua_State *L, const char *key, int n) { + lua_pushstring(L, key); + return (lua_rawget(L, -n) != LUA_TNIL); +} + + +/* +** Check that 'arg' either is a table or can behave like one (that is, +** has a metatable with the required metamethods) +*/ +static void checktab (lua_State *L, int arg, int what) { + if (lua_type(L, arg) != LUA_TTABLE) { /* is it not a table? */ + int n = 1; /* number of elements to pop */ + if (lua_getmetatable(L, arg) && /* must have metatable */ + (!(what & TAB_R) || checkfield(L, "__index", ++n)) && + (!(what & TAB_W) || checkfield(L, "__newindex", ++n)) && + (!(what & TAB_L) || checkfield(L, "__len", ++n))) { + lua_pop(L, n); /* pop metatable and tested metamethods */ + } + else + luaL_checktype(L, arg, LUA_TTABLE); /* force an error */ + } +} + + +#if defined(LUA_COMPAT_MAXN) +static int maxn (lua_State *L) { + lua_Number max = 0; + luaL_checktype(L, 1, LUA_TTABLE); + lua_pushnil(L); /* first key */ + while (lua_next(L, 1)) { + lua_pop(L, 1); /* remove value */ + if (lua_type(L, -1) == LUA_TNUMBER) { + lua_Number v = lua_tonumber(L, -1); + if (v > max) max = v; + } + } + lua_pushnumber(L, max); + return 1; +} +#endif + + +static int tinsert (lua_State *L) { + lua_Integer e = aux_getn(L, 1, TAB_RW) + 1; /* first empty element */ + lua_Integer pos; /* where to insert new element */ + switch (lua_gettop(L)) { + case 2: { /* called with only 2 arguments */ + pos = e; /* insert new element at the end */ + break; + } + case 3: { + lua_Integer i; + pos = luaL_checkinteger(L, 2); /* 2nd argument is the position */ + luaL_argcheck(L, 1 <= pos && pos <= e, 2, "position out of bounds"); + for (i = e; i > pos; i--) { /* move up elements */ + lua_geti(L, 1, i - 1); + lua_seti(L, 1, i); /* t[i] = t[i - 1] */ + } + break; + } + default: { + return luaL_error(L, "wrong number of arguments to 'insert'"); + } + } + lua_seti(L, 1, pos); /* t[pos] = v */ + return 0; +} + + +static int tremove (lua_State *L) { + lua_Integer size = aux_getn(L, 1, TAB_RW); + lua_Integer pos = luaL_optinteger(L, 2, size); + if (pos != size) /* validate 'pos' if given */ + luaL_argcheck(L, 1 <= pos && pos <= size + 1, 1, "position out of bounds"); + lua_geti(L, 1, pos); /* result = t[pos] */ + for ( ; pos < size; pos++) { + lua_geti(L, 1, pos + 1); + lua_seti(L, 1, pos); /* t[pos] = t[pos + 1] */ + } + lua_pushnil(L); + lua_seti(L, 1, pos); /* t[pos] = nil */ + return 1; +} + + +/* +** Copy elements (1[f], ..., 1[e]) into (tt[t], tt[t+1], ...). Whenever +** possible, copy in increasing order, which is better for rehashing. +** "possible" means destination after original range, or smaller +** than origin, or copying to another table. +*/ +static int tmove (lua_State *L) { + lua_Integer f = luaL_checkinteger(L, 2); + lua_Integer e = luaL_checkinteger(L, 3); + lua_Integer t = luaL_checkinteger(L, 4); + int tt = !lua_isnoneornil(L, 5) ? 5 : 1; /* destination table */ + checktab(L, 1, TAB_R); + checktab(L, tt, TAB_W); + if (e >= f) { /* otherwise, nothing to move */ + lua_Integer n, i; + luaL_argcheck(L, f > 0 || e < LUA_MAXINTEGER + f, 3, + "too many elements to move"); + n = e - f + 1; /* number of elements to move */ + luaL_argcheck(L, t <= LUA_MAXINTEGER - n + 1, 4, + "destination wrap around"); + if (t > e || t <= f || (tt != 1 && !lua_compare(L, 1, tt, LUA_OPEQ))) { + for (i = 0; i < n; i++) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + else { + for (i = n - 1; i >= 0; i--) { + lua_geti(L, 1, f + i); + lua_seti(L, tt, t + i); + } + } + } + lua_pushvalue(L, tt); /* return destination table */ + return 1; +} + + +static void addfield (lua_State *L, luaL_Buffer *b, lua_Integer i) { + lua_geti(L, 1, i); + if (!lua_isstring(L, -1)) + luaL_error(L, "invalid value (%s) at index %d in table for 'concat'", + luaL_typename(L, -1), i); + luaL_addvalue(b); +} + + +static int tconcat (lua_State *L) { + luaL_Buffer b; + lua_Integer last = aux_getn(L, 1, TAB_R); + size_t lsep; + const char *sep = luaL_optlstring(L, 2, "", &lsep); + lua_Integer i = luaL_optinteger(L, 3, 1); + last = luaL_optinteger(L, 4, last); + luaL_buffinit(L, &b); + for (; i < last; i++) { + addfield(L, &b, i); + luaL_addlstring(&b, sep, lsep); + } + if (i == last) /* add last value (if interval was not empty) */ + addfield(L, &b, i); + luaL_pushresult(&b); + return 1; +} + + +/* +** {====================================================== +** Pack/unpack +** ======================================================= +*/ + +static int pack (lua_State *L) { + int i; + int n = lua_gettop(L); /* number of elements to pack */ + lua_createtable(L, n, 1); /* create result table */ + lua_insert(L, 1); /* put it at index 1 */ + for (i = n; i >= 1; i--) /* assign elements */ + lua_seti(L, 1, i); + lua_pushinteger(L, n); + lua_setfield(L, 1, "n"); /* t.n = number of elements */ + return 1; /* return table */ +} + + +static int unpack (lua_State *L) { + lua_Unsigned n; + lua_Integer i = luaL_optinteger(L, 2, 1); + lua_Integer e = luaL_opt(L, luaL_checkinteger, 3, luaL_len(L, 1)); + if (i > e) return 0; /* empty range */ + n = (lua_Unsigned)e - i; /* number of elements minus 1 (avoid overflows) */ + if (n >= (unsigned int)INT_MAX || !lua_checkstack(L, (int)(++n))) + return luaL_error(L, "too many results to unpack"); + for (; i < e; i++) { /* push arg[i..e - 1] (to avoid overflows) */ + lua_geti(L, 1, i); + } + lua_geti(L, 1, e); /* push last element */ + return (int)n; +} + +/* }====================================================== */ + + + +/* +** {====================================================== +** Quicksort +** (based on 'Algorithms in MODULA-3', Robert Sedgewick; +** Addison-Wesley, 1993.) +** ======================================================= +*/ + + +/* type for array indices */ +typedef unsigned int IdxT; + + +/* +** Produce a "random" 'unsigned int' to randomize pivot choice. This +** macro is used only when 'sort' detects a big imbalance in the result +** of a partition. (If you don't want/need this "randomness", ~0 is a +** good choice.) +*/ +#if !defined(l_randomizePivot) /* { */ + +#include + +/* size of 'e' measured in number of 'unsigned int's */ +#define sof(e) (sizeof(e) / sizeof(unsigned int)) + +/* +** Use 'time' and 'clock' as sources of "randomness". Because we don't +** know the types 'clock_t' and 'time_t', we cannot cast them to +** anything without risking overflows. A safe way to use their values +** is to copy them to an array of a known type and use the array values. +*/ +static unsigned int l_randomizePivot (void) { + clock_t c = clock(); + time_t t = time(NULL); + unsigned int buff[sof(c) + sof(t)]; + unsigned int i, rnd = 0; + memcpy(buff, &c, sof(c) * sizeof(unsigned int)); + memcpy(buff + sof(c), &t, sof(t) * sizeof(unsigned int)); + for (i = 0; i < sof(buff); i++) + rnd += buff[i]; + return rnd; +} + +#endif /* } */ + + +/* arrays larger than 'RANLIMIT' may use randomized pivots */ +#define RANLIMIT 100u + + +static void set2 (lua_State *L, IdxT i, IdxT j) { + lua_seti(L, 1, i); + lua_seti(L, 1, j); +} + + +/* +** Return true iff value at stack index 'a' is less than the value at +** index 'b' (according to the order of the sort). +*/ +static int sort_comp (lua_State *L, int a, int b) { + if (lua_isnil(L, 2)) /* no function? */ + return lua_compare(L, a, b, LUA_OPLT); /* a < b */ + else { /* function */ + int res; + lua_pushvalue(L, 2); /* push function */ + lua_pushvalue(L, a-1); /* -1 to compensate function */ + lua_pushvalue(L, b-2); /* -2 to compensate function and 'a' */ + lua_call(L, 2, 1); /* call function */ + res = lua_toboolean(L, -1); /* get result */ + lua_pop(L, 1); /* pop result */ + return res; + } +} + + +/* +** Does the partition: Pivot P is at the top of the stack. +** precondition: a[lo] <= P == a[up-1] <= a[up], +** so it only needs to do the partition from lo + 1 to up - 2. +** Pos-condition: a[lo .. i - 1] <= a[i] == P <= a[i + 1 .. up] +** returns 'i'. +*/ +static IdxT partition (lua_State *L, IdxT lo, IdxT up) { + IdxT i = lo; /* will be incremented before first use */ + IdxT j = up - 1; /* will be decremented before first use */ + /* loop invariant: a[lo .. i] <= P <= a[j .. up] */ + for (;;) { + /* next loop: repeat ++i while a[i] < P */ + while (lua_geti(L, 1, ++i), sort_comp(L, -1, -2)) { + if (i == up - 1) /* a[i] < P but a[up - 1] == P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[i] */ + } + /* after the loop, a[i] >= P and a[lo .. i - 1] < P */ + /* next loop: repeat --j while P < a[j] */ + while (lua_geti(L, 1, --j), sort_comp(L, -3, -1)) { + if (j < i) /* j < i but a[j] > P ?? */ + luaL_error(L, "invalid order function for sorting"); + lua_pop(L, 1); /* remove a[j] */ + } + /* after the loop, a[j] <= P and a[j + 1 .. up] >= P */ + if (j < i) { /* no elements out of place? */ + /* a[lo .. i - 1] <= P <= a[j + 1 .. i .. up] */ + lua_pop(L, 1); /* pop a[j] */ + /* swap pivot (a[up - 1]) with a[i] to satisfy pos-condition */ + set2(L, up - 1, i); + return i; + } + /* otherwise, swap a[i] - a[j] to restore invariant and repeat */ + set2(L, i, j); + } +} + + +/* +** Choose an element in the middle (2nd-3th quarters) of [lo,up] +** "randomized" by 'rnd' +*/ +static IdxT choosePivot (IdxT lo, IdxT up, unsigned int rnd) { + IdxT r4 = (up - lo) / 4; /* range/4 */ + IdxT p = rnd % (r4 * 2) + (lo + r4); + lua_assert(lo + r4 <= p && p <= up - r4); + return p; +} + + +/* +** QuickSort algorithm (recursive function) +*/ +static void auxsort (lua_State *L, IdxT lo, IdxT up, + unsigned int rnd) { + while (lo < up) { /* loop for tail recursion */ + IdxT p; /* Pivot index */ + IdxT n; /* to be used later */ + /* sort elements 'lo', 'p', and 'up' */ + lua_geti(L, 1, lo); + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[lo]? */ + set2(L, lo, up); /* swap a[lo] - a[up] */ + else + lua_pop(L, 2); /* remove both values */ + if (up - lo == 1) /* only 2 elements? */ + return; /* already sorted */ + if (up - lo < RANLIMIT || rnd == 0) /* small interval or no randomize? */ + p = (lo + up)/2; /* middle element is a good pivot */ + else /* for larger intervals, it is worth a random pivot */ + p = choosePivot(lo, up, rnd); + lua_geti(L, 1, p); + lua_geti(L, 1, lo); + if (sort_comp(L, -2, -1)) /* a[p] < a[lo]? */ + set2(L, p, lo); /* swap a[p] - a[lo] */ + else { + lua_pop(L, 1); /* remove a[lo] */ + lua_geti(L, 1, up); + if (sort_comp(L, -1, -2)) /* a[up] < a[p]? */ + set2(L, p, up); /* swap a[up] - a[p] */ + else + lua_pop(L, 2); + } + if (up - lo == 2) /* only 3 elements? */ + return; /* already sorted */ + lua_geti(L, 1, p); /* get middle element (Pivot) */ + lua_pushvalue(L, -1); /* push Pivot */ + lua_geti(L, 1, up - 1); /* push a[up - 1] */ + set2(L, p, up - 1); /* swap Pivot (a[p]) with a[up - 1] */ + p = partition(L, lo, up); + /* a[lo .. p - 1] <= a[p] == P <= a[p + 1 .. up] */ + if (p - lo < up - p) { /* lower interval is smaller? */ + auxsort(L, lo, p - 1, rnd); /* call recursively for lower interval */ + n = p - lo; /* size of smaller interval */ + lo = p + 1; /* tail call for [p + 1 .. up] (upper interval) */ + } + else { + auxsort(L, p + 1, up, rnd); /* call recursively for upper interval */ + n = up - p; /* size of smaller interval */ + up = p - 1; /* tail call for [lo .. p - 1] (lower interval) */ + } + if ((up - lo) / 128 > n) /* partition too imbalanced? */ + rnd = l_randomizePivot(); /* try a new randomization */ + } /* tail call auxsort(L, lo, up, rnd) */ +} + + +static int sort (lua_State *L) { + lua_Integer n = aux_getn(L, 1, TAB_RW); + if (n > 1) { /* non-trivial interval? */ + luaL_argcheck(L, n < INT_MAX, 1, "array too big"); + if (!lua_isnoneornil(L, 2)) /* is there a 2nd argument? */ + luaL_checktype(L, 2, LUA_TFUNCTION); /* must be a function */ + lua_settop(L, 2); /* make sure there are two arguments */ + auxsort(L, 1, (IdxT)n, 0); + } + return 0; +} + +/* }====================================================== */ + + +static const luaL_Reg tab_funcs[] = { + {"concat", tconcat}, +#if defined(LUA_COMPAT_MAXN) + {"maxn", maxn}, +#endif + {"insert", tinsert}, + {"pack", pack}, + {"unpack", unpack}, + {"remove", tremove}, + {"move", tmove}, + {"sort", sort}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_table (lua_State *L) { + luaL_newlib(L, tab_funcs); +#if defined(LUA_COMPAT_UNPACK) + /* _G.unpack = table.unpack */ + lua_getfield(L, -1, "unpack"); + lua_setglobal(L, "unpack"); +#endif + return 1; +} + diff --git a/src/lua/ltm.c b/src/lua/ltm.c new file mode 100644 index 000000000000..0e7c713214cb --- /dev/null +++ b/src/lua/ltm.c @@ -0,0 +1,165 @@ +/* +** $Id: ltm.c,v 2.38.1.1 2017/04/19 17:39:34 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#define ltm_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lobject.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + +static const char udatatypename[] = "userdata"; + +LUAI_DDEF const char *const luaT_typenames_[LUA_TOTALTAGS] = { + "no value", + "nil", "boolean", udatatypename, "number", + "string", "table", "function", udatatypename, "thread", + "proto" /* this last case is used for tests only */ +}; + + +void luaT_init (lua_State *L) { + static const char *const luaT_eventname[] = { /* ORDER TM */ + "__index", "__newindex", + "__gc", "__mode", "__len", "__eq", + "__add", "__sub", "__mul", "__mod", "__pow", + "__div", "__idiv", + "__band", "__bor", "__bxor", "__shl", "__shr", + "__unm", "__bnot", "__lt", "__le", + "__concat", "__call" + }; + int i; + for (i=0; itmname[i] = luaS_new(L, luaT_eventname[i]); + luaC_fix(L, obj2gco(G(L)->tmname[i])); /* never collect these names */ + } +} + + +/* +** function to be used with macro "fasttm": optimized for absence of +** tag methods +*/ +const TValue *luaT_gettm (Table *events, TMS event, TString *ename) { + const TValue *tm = luaH_getshortstr(events, ename); + lua_assert(event <= TM_EQ); + if (ttisnil(tm)) { /* no tag method? */ + events->flags |= cast_byte(1u<metatable; + break; + case LUA_TUSERDATA: + mt = uvalue(o)->metatable; + break; + default: + mt = G(L)->mt[ttnov(o)]; + } + return (mt ? luaH_getshortstr(mt, G(L)->tmname[event]) : luaO_nilobject); +} + + +/* +** Return the name of the type of an object. For tables and userdata +** with metatable, use their '__name' metafield, if present. +*/ +const char *luaT_objtypename (lua_State *L, const TValue *o) { + Table *mt; + if ((ttistable(o) && (mt = hvalue(o)->metatable) != NULL) || + (ttisfulluserdata(o) && (mt = uvalue(o)->metatable) != NULL)) { + const TValue *name = luaH_getshortstr(mt, luaS_new(L, "__name")); + if (ttisstring(name)) /* is '__name' a string? */ + return getstr(tsvalue(name)); /* use it as type name */ + } + return ttypename(ttnov(o)); /* else use standard type name */ +} + + +void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres) { + ptrdiff_t result = savestack(L, p3); + StkId func = L->top; + setobj2s(L, func, f); /* push function (assume EXTRA_STACK) */ + setobj2s(L, func + 1, p1); /* 1st argument */ + setobj2s(L, func + 2, p2); /* 2nd argument */ + L->top += 3; + if (!hasres) /* no result? 'p3' is third argument */ + setobj2s(L, L->top++, p3); /* 3rd argument */ + /* metamethod may yield only when called from Lua code */ + if (isLua(L->ci)) + luaD_call(L, func, hasres); + else + luaD_callnoyield(L, func, hasres); + if (hasres) { /* if has result, move it to its place */ + p3 = restorestack(L, result); + setobjs2s(L, p3, --L->top); + } +} + + +int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + const TValue *tm = luaT_gettmbyobj(L, p1, event); /* try first operand */ + if (ttisnil(tm)) + tm = luaT_gettmbyobj(L, p2, event); /* try second operand */ + if (ttisnil(tm)) return 0; + luaT_callTM(L, tm, p1, p2, res, 1); + return 1; +} + + +void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event) { + if (!luaT_callbinTM(L, p1, p2, res, event)) { + switch (event) { + case TM_CONCAT: + luaG_concaterror(L, p1, p2); + /* call never returns, but to avoid warnings: *//* FALLTHROUGH */ + case TM_BAND: case TM_BOR: case TM_BXOR: + case TM_SHL: case TM_SHR: case TM_BNOT: { + lua_Number dummy; + if (tonumber(p1, &dummy) && tonumber(p2, &dummy)) + luaG_tointerror(L, p1, p2); + else + luaG_opinterror(L, p1, p2, "perform bitwise operation on"); + } + /* calls never return, but to avoid warnings: *//* FALLTHROUGH */ + default: + luaG_opinterror(L, p1, p2, "perform arithmetic on"); + } + } +} + + +int luaT_callorderTM (lua_State *L, const TValue *p1, const TValue *p2, + TMS event) { + if (!luaT_callbinTM(L, p1, p2, L->top, event)) + return -1; /* no metamethod */ + else + return !l_isfalse(L->top); +} + diff --git a/src/lua/ltm.h b/src/lua/ltm.h new file mode 100644 index 000000000000..8170688daeb2 --- /dev/null +++ b/src/lua/ltm.h @@ -0,0 +1,76 @@ +/* +** $Id: ltm.h,v 2.22.1.1 2017/04/19 17:20:42 roberto Exp $ +** Tag methods +** See Copyright Notice in lua.h +*/ + +#ifndef ltm_h +#define ltm_h + + +#include "lobject.h" + + +/* +* WARNING: if you change the order of this enumeration, +* grep "ORDER TM" and "ORDER OP" +*/ +typedef enum { + TM_INDEX, + TM_NEWINDEX, + TM_GC, + TM_MODE, + TM_LEN, + TM_EQ, /* last tag method with fast access */ + TM_ADD, + TM_SUB, + TM_MUL, + TM_MOD, + TM_POW, + TM_DIV, + TM_IDIV, + TM_BAND, + TM_BOR, + TM_BXOR, + TM_SHL, + TM_SHR, + TM_UNM, + TM_BNOT, + TM_LT, + TM_LE, + TM_CONCAT, + TM_CALL, + TM_N /* number of elements in the enum */ +} TMS; + + + +#define gfasttm(g,et,e) ((et) == NULL ? NULL : \ + ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) + +#define fasttm(l,et,e) gfasttm(G(l), et, e) + +#define ttypename(x) luaT_typenames_[(x) + 1] + +LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; + + +LUAI_FUNC const char *luaT_objtypename (lua_State *L, const TValue *o); + +LUAI_FUNC const TValue *luaT_gettm (Table *events, TMS event, TString *ename); +LUAI_FUNC const TValue *luaT_gettmbyobj (lua_State *L, const TValue *o, + TMS event); +LUAI_FUNC void luaT_init (lua_State *L); + +LUAI_FUNC void luaT_callTM (lua_State *L, const TValue *f, const TValue *p1, + const TValue *p2, TValue *p3, int hasres); +LUAI_FUNC int luaT_callbinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event); +LUAI_FUNC void luaT_trybinTM (lua_State *L, const TValue *p1, const TValue *p2, + StkId res, TMS event); +LUAI_FUNC int luaT_callorderTM (lua_State *L, const TValue *p1, + const TValue *p2, TMS event); + + + +#endif diff --git a/src/lua/lua.h b/src/lua/lua.h new file mode 100644 index 000000000000..9394c5ef8fd6 --- /dev/null +++ b/src/lua/lua.h @@ -0,0 +1,485 @@ +/* +** Lua - A Scripting Language +** Lua.org, PUC-Rio, Brazil (http://www.lua.org) +** See Copyright Notice at the end of this file +*/ + + +#ifndef lua_h +#define lua_h + +#include +#include + + +#include "luaconf.h" + + +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "3" +#define LUA_VERSION_NUM 503 +#define LUA_VERSION_RELEASE "6" + +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2020 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" + + +/* mark for precompiled code ('Lua') */ +#define LUA_SIGNATURE "\x1bLua" + +/* option for multiple returns in 'lua_pcall' and 'lua_call' */ +#define LUA_MULTRET (-1) + + +/* +** Pseudo-indices +** (-LUAI_MAXSTACK is the minimum valid index; we keep some free empty +** space after that to help overflow detection) +*/ +#define LUA_REGISTRYINDEX (-LUAI_MAXSTACK - 1000) +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) + + +/* thread status */ +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 + + +typedef struct lua_State lua_State; + + +/* +** basic types +*/ +#define LUA_TNONE (-1) + +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 + +#define LUA_NUMTAGS 9 + + + +/* minimum Lua stack available to a C function */ +#define LUA_MINSTACK 20 + + +/* predefined values in the registry */ +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS + + +/* type of numbers in Lua */ +typedef LUA_NUMBER lua_Number; + + +/* type for integer functions */ +typedef LUA_INTEGER lua_Integer; + +/* unsigned integer type */ +typedef LUA_UNSIGNED lua_Unsigned; + +/* type for continuation-function contexts */ +typedef LUA_KCONTEXT lua_KContext; + + +/* +** Type for C functions registered with Lua +*/ +typedef int (*lua_CFunction) (lua_State *L); + +/* +** Type for continuation functions +*/ +typedef int (*lua_KFunction) (lua_State *L, int status, lua_KContext ctx); + + +/* +** Type for functions that read/write blocks when loading/dumping Lua chunks +*/ +typedef const char * (*lua_Reader) (lua_State *L, void *ud, size_t *sz); + +typedef int (*lua_Writer) (lua_State *L, const void *p, size_t sz, void *ud); + + +/* +** Type for memory-allocation functions +*/ +typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); + + + +/* +** generic extra include file +*/ +#if defined(LUA_USER_H) +#include LUA_USER_H +#endif + + +/* +** RCS ident string +*/ +extern const char lua_ident[]; + + +/* +** state manipulation +*/ +LUA_API lua_State *(lua_newstate) (lua_Alloc f, void *ud); +LUA_API void (lua_close) (lua_State *L); +LUA_API lua_State *(lua_newthread) (lua_State *L); + +LUA_API lua_CFunction (lua_atpanic) (lua_State *L, lua_CFunction panicf); + + +LUA_API const lua_Number *(lua_version) (lua_State *L); + + +/* +** basic stack manipulation +*/ +LUA_API int (lua_absindex) (lua_State *L, int idx); +LUA_API int (lua_gettop) (lua_State *L); +LUA_API void (lua_settop) (lua_State *L, int idx); +LUA_API void (lua_pushvalue) (lua_State *L, int idx); +LUA_API void (lua_rotate) (lua_State *L, int idx, int n); +LUA_API void (lua_copy) (lua_State *L, int fromidx, int toidx); +LUA_API int (lua_checkstack) (lua_State *L, int n); + +LUA_API void (lua_xmove) (lua_State *from, lua_State *to, int n); + + +/* +** access functions (stack -> C) +*/ + +LUA_API int (lua_isnumber) (lua_State *L, int idx); +LUA_API int (lua_isstring) (lua_State *L, int idx); +LUA_API int (lua_iscfunction) (lua_State *L, int idx); +LUA_API int (lua_isinteger) (lua_State *L, int idx); +LUA_API int (lua_isuserdata) (lua_State *L, int idx); +LUA_API int (lua_type) (lua_State *L, int idx); +LUA_API const char *(lua_typename) (lua_State *L, int tp); + +LUA_API lua_Number (lua_tonumberx) (lua_State *L, int idx, int *isnum); +LUA_API lua_Integer (lua_tointegerx) (lua_State *L, int idx, int *isnum); +LUA_API int (lua_toboolean) (lua_State *L, int idx); +LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); +LUA_API size_t (lua_rawlen) (lua_State *L, int idx); +LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); +LUA_API const void *(lua_topointer) (lua_State *L, int idx); + + +/* +** Comparison and arithmetic functions +*/ + +#define LUA_OPADD 0 /* ORDER TM, ORDER OP */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPMOD 3 +#define LUA_OPPOW 4 +#define LUA_OPDIV 5 +#define LUA_OPIDIV 6 +#define LUA_OPBAND 7 +#define LUA_OPBOR 8 +#define LUA_OPBXOR 9 +#define LUA_OPSHL 10 +#define LUA_OPSHR 11 +#define LUA_OPUNM 12 +#define LUA_OPBNOT 13 + +LUA_API void (lua_arith) (lua_State *L, int op); + +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 + +LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); +LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); + + +/* +** push functions (C -> stack) +*/ +LUA_API void (lua_pushnil) (lua_State *L); +LUA_API void (lua_pushnumber) (lua_State *L, lua_Number n); +LUA_API void (lua_pushinteger) (lua_State *L, lua_Integer n); +LUA_API const char *(lua_pushlstring) (lua_State *L, const char *s, size_t len); +LUA_API const char *(lua_pushstring) (lua_State *L, const char *s); +LUA_API const char *(lua_pushvfstring) (lua_State *L, const char *fmt, + va_list argp); +LUA_API const char *(lua_pushfstring) (lua_State *L, const char *fmt, ...); +LUA_API void (lua_pushcclosure) (lua_State *L, lua_CFunction fn, int n); +LUA_API void (lua_pushboolean) (lua_State *L, int b); +LUA_API void (lua_pushlightuserdata) (lua_State *L, void *p); +LUA_API int (lua_pushthread) (lua_State *L); + + +/* +** get functions (Lua -> stack) +*/ +LUA_API int (lua_getglobal) (lua_State *L, const char *name); +LUA_API int (lua_gettable) (lua_State *L, int idx); +LUA_API int (lua_getfield) (lua_State *L, int idx, const char *k); +LUA_API int (lua_geti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawget) (lua_State *L, int idx); +LUA_API int (lua_rawgeti) (lua_State *L, int idx, lua_Integer n); +LUA_API int (lua_rawgetp) (lua_State *L, int idx, const void *p); + +LUA_API void (lua_createtable) (lua_State *L, int narr, int nrec); +LUA_API void *(lua_newuserdata) (lua_State *L, size_t sz); +LUA_API int (lua_getmetatable) (lua_State *L, int objindex); +LUA_API int (lua_getuservalue) (lua_State *L, int idx); + + +/* +** set functions (stack -> Lua) +*/ +LUA_API void (lua_setglobal) (lua_State *L, const char *name); +LUA_API void (lua_settable) (lua_State *L, int idx); +LUA_API void (lua_setfield) (lua_State *L, int idx, const char *k); +LUA_API void (lua_seti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawset) (lua_State *L, int idx); +LUA_API void (lua_rawseti) (lua_State *L, int idx, lua_Integer n); +LUA_API void (lua_rawsetp) (lua_State *L, int idx, const void *p); +LUA_API int (lua_setmetatable) (lua_State *L, int objindex); +LUA_API void (lua_setuservalue) (lua_State *L, int idx); + + +/* +** 'load' and 'call' functions (load and run Lua code) +*/ +LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, + lua_KContext ctx, lua_KFunction k); +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) + +LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, + lua_KContext ctx, lua_KFunction k); +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) + +LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, + const char *chunkname, const char *mode); + +LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data, int strip); + + +/* +** coroutine functions +*/ +LUA_API int (lua_yieldk) (lua_State *L, int nresults, lua_KContext ctx, + lua_KFunction k); +LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); +LUA_API int (lua_status) (lua_State *L); +LUA_API int (lua_isyieldable) (lua_State *L); + +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) + + +/* +** garbage-collection function and options +*/ + +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCISRUNNING 9 + +LUA_API int (lua_gc) (lua_State *L, int what, int data); + + +/* +** miscellaneous functions +*/ + +LUA_API int (lua_error) (lua_State *L); + +LUA_API int (lua_next) (lua_State *L, int idx); + +LUA_API void (lua_concat) (lua_State *L, int n); +LUA_API void (lua_len) (lua_State *L, int idx); + +LUA_API size_t (lua_stringtonumber) (lua_State *L, const char *s); + +LUA_API lua_Alloc (lua_getallocf) (lua_State *L, void **ud); +LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); + + + +/* +** {============================================================== +** some useful macros +** =============================================================== +*/ + +#define lua_getextraspace(L) ((void *)((char *)(L) - LUA_EXTRASPACE)) + +#define lua_tonumber(L,i) lua_tonumberx(L,(i),NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,(i),NULL) + +#define lua_pop(L,n) lua_settop(L, -(n)-1) + +#define lua_newtable(L) lua_createtable(L, 0, 0) + +#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) + +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) + +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) + +#define lua_pushliteral(L, s) lua_pushstring(L, "" s) + +#define lua_pushglobaltable(L) \ + ((void)lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS)) + +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) + + +#define lua_insert(L,idx) lua_rotate(L, (idx), 1) + +#define lua_remove(L,idx) (lua_rotate(L, (idx), -1), lua_pop(L, 1)) + +#define lua_replace(L,idx) (lua_copy(L, -1, (idx)), lua_pop(L, 1)) + +/* }============================================================== */ + + +/* +** {============================================================== +** compatibility macros for unsigned conversions +** =============================================================== +*/ +#if defined(LUA_COMPAT_APIINTCASTS) + +#define lua_pushunsigned(L,n) lua_pushinteger(L, (lua_Integer)(n)) +#define lua_tounsignedx(L,i,is) ((lua_Unsigned)lua_tointegerx(L,i,is)) +#define lua_tounsigned(L,i) lua_tounsignedx(L,(i),NULL) + +#endif +/* }============================================================== */ + +/* +** {====================================================================== +** Debug API +** ======================================================================= +*/ + + +/* +** Event codes +*/ +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 +#define LUA_HOOKTAILCALL 4 + + +/* +** Event masks +*/ +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) + +typedef struct lua_Debug lua_Debug; /* activation record */ + + +/* Functions to be called by the debugger in specific events */ +typedef void (*lua_Hook) (lua_State *L, lua_Debug *ar); + + +LUA_API int (lua_getstack) (lua_State *L, int level, lua_Debug *ar); +LUA_API int (lua_getinfo) (lua_State *L, const char *what, lua_Debug *ar); +LUA_API const char *(lua_getlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_setlocal) (lua_State *L, const lua_Debug *ar, int n); +LUA_API const char *(lua_getupvalue) (lua_State *L, int funcindex, int n); +LUA_API const char *(lua_setupvalue) (lua_State *L, int funcindex, int n); + +LUA_API void *(lua_upvalueid) (lua_State *L, int fidx, int n); +LUA_API void (lua_upvaluejoin) (lua_State *L, int fidx1, int n1, + int fidx2, int n2); + +LUA_API void (lua_sethook) (lua_State *L, lua_Hook func, int mask, int count); +LUA_API lua_Hook (lua_gethook) (lua_State *L); +LUA_API int (lua_gethookmask) (lua_State *L); +LUA_API int (lua_gethookcount) (lua_State *L); + + +struct lua_Debug { + int event; + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ + unsigned char nparams;/* (u) number of parameters */ + char isvararg; /* (u) */ + char istailcall; /* (t) */ + char short_src[LUA_IDSIZE]; /* (S) */ + /* private part */ + struct CallInfo *i_ci; /* active function */ +}; + +/* }====================================================================== */ + + +/****************************************************************************** +* Copyright (C) 1994-2020 Lua.org, PUC-Rio. +* +* Permission is hereby granted, free of charge, to any person obtaining +* a copy of this software and associated documentation files (the +* "Software"), to deal in the Software without restriction, including +* without limitation the rights to use, copy, modify, merge, publish, +* distribute, sublicense, and/or sell copies of the Software, and to +* permit persons to whom the Software is furnished to do so, subject to +* the following conditions: +* +* The above copyright notice and this permission notice shall be +* included in all copies or substantial portions of the Software. +* +* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +******************************************************************************/ + + +#endif diff --git a/src/lua/lua.hpp b/src/lua/lua.hpp new file mode 100644 index 000000000000..ec417f59469c --- /dev/null +++ b/src/lua/lua.hpp @@ -0,0 +1,9 @@ +// lua.hpp +// Lua header files for C++ +// <> not supplied automatically because Lua also compiles as C++ + +extern "C" { +#include "lua.h" +#include "lualib.h" +#include "lauxlib.h" +} diff --git a/src/lua/luaconf.h b/src/lua/luaconf.h new file mode 100644 index 000000000000..9eeeea69e205 --- /dev/null +++ b/src/lua/luaconf.h @@ -0,0 +1,790 @@ +/* +** $Id: luaconf.h,v 1.259.1.1 2017/04/19 17:29:57 roberto Exp $ +** Configuration file for Lua +** See Copyright Notice in lua.h +*/ + + +#ifndef luaconf_h +#define luaconf_h + +#include +#include + + +/* +** =================================================================== +** Search for "@@" to find all configurable definitions. +** =================================================================== +*/ + + +/* +** {==================================================================== +** System Configuration: macros to adapt (if needed) Lua to some +** particular platform, for instance compiling it with 32-bit numbers or +** restricting it to C89. +** ===================================================================== +*/ + +/* +@@ LUA_32BITS enables Lua with 32-bit integers and 32-bit floats. You +** can also define LUA_32BITS in the make file, but changing here you +** ensure that all software connected to Lua will be compiled with the +** same configuration. +*/ +/* #define LUA_32BITS */ + + +/* +@@ LUA_USE_C89 controls the use of non-ISO-C89 features. +** Define it if you want Lua to avoid the use of a few C99 features +** or Windows-specific features on Windows. +*/ +/* #define LUA_USE_C89 */ + + +/* +** By default, Lua on Windows use (some) specific Windows features +*/ +#if !defined(LUA_USE_C89) && defined(_WIN32) && !defined(_WIN32_WCE) +#define LUA_USE_WINDOWS /* enable goodies for regular Windows */ +#endif + + +#if defined(LUA_USE_WINDOWS) +#define LUA_DL_DLL /* enable support for DLL */ +#define LUA_USE_C89 /* broadly, Windows is C89 */ +#endif + + +#if defined(LUA_USE_LINUX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#endif + + +#if defined(LUA_USE_MACOSX) +#define LUA_USE_POSIX +#define LUA_USE_DLOPEN /* MacOS does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#endif + + +/* +@@ LUA_C89_NUMBERS ensures that Lua uses the largest types available for +** C89 ('long' and 'double'); Windows always has '__int64', so it does +** not need to use this case. +*/ +#if defined(LUA_USE_C89) && !defined(LUA_USE_WINDOWS) +#define LUA_C89_NUMBERS +#endif + + + +/* +@@ LUAI_BITSINT defines the (minimum) number of bits in an 'int'. +*/ +/* avoid undefined shifts */ +#if ((INT_MAX >> 15) >> 15) >= 1 +#define LUAI_BITSINT 32 +#else +/* 'int' always must have at least 16 bits */ +#define LUAI_BITSINT 16 +#endif + + +/* +@@ LUA_INT_TYPE defines the type for Lua integers. +@@ LUA_FLOAT_TYPE defines the type for Lua floats. +** Lua should work fine with any mix of these options (if supported +** by your C compiler). The usual configurations are 64-bit integers +** and 'double' (the default), 32-bit integers and 'float' (for +** restricted platforms), and 'long'/'double' (for C compilers not +** compliant with C99, which may not have support for 'long long'). +*/ + +/* predefined options for LUA_INT_TYPE */ +#define LUA_INT_INT 1 +#define LUA_INT_LONG 2 +#define LUA_INT_LONGLONG 3 + +/* predefined options for LUA_FLOAT_TYPE */ +#define LUA_FLOAT_FLOAT 1 +#define LUA_FLOAT_DOUBLE 2 +#define LUA_FLOAT_LONGDOUBLE 3 + +#if defined(LUA_32BITS) /* { */ +/* +** 32-bit integers and 'float' +*/ +#if LUAI_BITSINT >= 32 /* use 'int' if big enough */ +#define LUA_INT_TYPE LUA_INT_INT +#else /* otherwise use 'long' */ +#define LUA_INT_TYPE LUA_INT_LONG +#endif +#define LUA_FLOAT_TYPE LUA_FLOAT_FLOAT + +#elif defined(LUA_C89_NUMBERS) /* }{ */ +/* +** largest types available for C89 ('long' and 'double') +*/ +#define LUA_INT_TYPE LUA_INT_LONG +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE + +#endif /* } */ + + +/* +** default configuration for 64-bit Lua ('long long' and 'double') +*/ +#if !defined(LUA_INT_TYPE) +#define LUA_INT_TYPE LUA_INT_LONGLONG +#endif + +#if !defined(LUA_FLOAT_TYPE) +#define LUA_FLOAT_TYPE LUA_FLOAT_DOUBLE +#endif + +/* }================================================================== */ + + + + +/* +** {================================================================== +** Configuration for Paths. +** =================================================================== +*/ + +/* +** LUA_PATH_SEP is the character that separates templates in a path. +** LUA_PATH_MARK is the string that marks the substitution points in a +** template. +** LUA_EXEC_DIR in a Windows path is replaced by the executable's +** directory. +*/ +#define LUA_PATH_SEP ";" +#define LUA_PATH_MARK "?" +#define LUA_EXEC_DIR "!" + + +/* +@@ LUA_PATH_DEFAULT is the default path that Lua uses to look for +** Lua libraries. +@@ LUA_CPATH_DEFAULT is the default path that Lua uses to look for +** C libraries. +** CHANGE them if your machine has a non-conventional directory +** hierarchy or if you want to install your libraries in +** non-conventional directories. +*/ +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#if defined(_WIN32) /* { */ +/* +** In Windows, any exclamation mark ('!') in the path is replaced by the +** path of the directory of the executable file of the current process. +*/ +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" +#define LUA_SHRDIR "!\\..\\share\\lua\\" LUA_VDIR "\\" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" \ + LUA_SHRDIR"?.lua;" LUA_SHRDIR"?\\init.lua;" \ + ".\\?.lua;" ".\\?\\init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.dll;" \ + LUA_CDIR"..\\lib\\lua\\" LUA_VDIR "\\?.dll;" \ + LUA_CDIR"loadall.dll;" ".\\?.dll" + +#else /* }{ */ + +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR "/" +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR "/" +#define LUA_PATH_DEFAULT \ + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" \ + "./?.lua;" "./?/init.lua" +#define LUA_CPATH_DEFAULT \ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ + + +/* +@@ LUA_DIRSEP is the directory separator (for submodules). +** CHANGE it if your machine does not use "/" as the directory separator +** and is not Windows. (On Windows Lua automatically uses "\".) +*/ +#if defined(_WIN32) +#define LUA_DIRSEP "\\" +#else +#define LUA_DIRSEP "/" +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Marks for exported symbols in the C code +** =================================================================== +*/ + +/* +@@ LUA_API is a mark for all core API functions. +@@ LUALIB_API is a mark for all auxiliary library functions. +@@ LUAMOD_API is a mark for all standard library opening functions. +** CHANGE them if you need to define those functions in some special way. +** For instance, if you want to create one Windows DLL with the core and +** the libraries, you may want to use the following definition (define +** LUA_BUILD_AS_DLL to get it). +*/ +#if defined(LUA_BUILD_AS_DLL) /* { */ + +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#define LUA_API __declspec(dllexport) +#else /* }{ */ +#define LUA_API __declspec(dllimport) +#endif /* } */ + +#else /* }{ */ + +#define LUA_API extern + +#endif /* } */ + + +/* more often than not the libs go together with the core */ +#define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API + + +/* +@@ LUAI_FUNC is a mark for all extern functions that are not to be +** exported to outside modules. +@@ LUAI_DDEF and LUAI_DDEC are marks for all extern (const) variables +** that are not to be exported to outside modules (LUAI_DDEF for +** definitions and LUAI_DDEC for declarations). +** CHANGE them if you need to mark them in some special way. Elf/gcc +** (versions 3.2 and later) mark them as "hidden" to optimize access +** when Lua is compiled as a shared library. Not all elf targets support +** this attribute. Unfortunately, gcc does not offer a way to check +** whether the target offers that support, and those without support +** give a warning about it. To avoid these warnings, change to the +** default definition. +*/ +#if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#else /* }{ */ +#define LUAI_FUNC extern +#endif /* } */ + +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Compatibility with previous versions +** =================================================================== +*/ + +/* +@@ LUA_COMPAT_5_2 controls other macros for compatibility with Lua 5.2. +@@ LUA_COMPAT_5_1 controls other macros for compatibility with Lua 5.1. +** You can define it to get all options, or change specific options +** to fit your specific needs. +*/ +#if defined(LUA_COMPAT_5_2) /* { */ + +/* +@@ LUA_COMPAT_MATHLIB controls the presence of several deprecated +** functions in the mathematical library. +*/ +#define LUA_COMPAT_MATHLIB + +/* +@@ LUA_COMPAT_BITLIB controls the presence of library 'bit32'. +*/ +#define LUA_COMPAT_BITLIB + +/* +@@ LUA_COMPAT_IPAIRS controls the effectiveness of the __ipairs metamethod. +*/ +#define LUA_COMPAT_IPAIRS + +/* +@@ LUA_COMPAT_APIINTCASTS controls the presence of macros for +** manipulating other integer types (lua_pushunsigned, lua_tounsigned, +** luaL_checkint, luaL_checklong, etc.) +*/ +#define LUA_COMPAT_APIINTCASTS + +#endif /* } */ + + +#if defined(LUA_COMPAT_5_1) /* { */ + +/* Incompatibilities from 5.2 -> 5.3 */ +#define LUA_COMPAT_MATHLIB +#define LUA_COMPAT_APIINTCASTS + +/* +@@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. +** You can replace it with 'table.unpack'. +*/ +#define LUA_COMPAT_UNPACK + +/* +@@ LUA_COMPAT_LOADERS controls the presence of table 'package.loaders'. +** You can replace it with 'package.searchers'. +*/ +#define LUA_COMPAT_LOADERS + +/* +@@ macro 'lua_cpcall' emulates deprecated function lua_cpcall. +** You can call your C function directly (with light C functions). +*/ +#define lua_cpcall(L,f,u) \ + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) + + +/* +@@ LUA_COMPAT_LOG10 defines the function 'log10' in the math library. +** You can rewrite 'log10(x)' as 'log(x, 10)'. +*/ +#define LUA_COMPAT_LOG10 + +/* +@@ LUA_COMPAT_LOADSTRING defines the function 'loadstring' in the base +** library. You can rewrite 'loadstring(s)' as 'load(s)'. +*/ +#define LUA_COMPAT_LOADSTRING + +/* +@@ LUA_COMPAT_MAXN defines the function 'maxn' in the table library. +*/ +#define LUA_COMPAT_MAXN + +/* +@@ The following macros supply trivial compatibility for some +** changes in the API. The macros themselves document how to +** change your code to avoid using them. +*/ +#define lua_strlen(L,i) lua_rawlen(L, (i)) + +#define lua_objlen(L,i) lua_rawlen(L, (i)) + +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) + +/* +@@ LUA_COMPAT_MODULE controls compatibility with previous +** module functions 'module' (Lua) and 'luaL_register' (C). +*/ +#define LUA_COMPAT_MODULE + +#endif /* } */ + + +/* +@@ LUA_COMPAT_FLOATSTRING makes Lua format integral floats without a +@@ a float mark ('.0'). +** This macro is not on by default even in compatibility mode, +** because this is not really an incompatibility. +*/ +/* #define LUA_COMPAT_FLOATSTRING */ + +/* }================================================================== */ + + + +/* +** {================================================================== +** Configuration for Numbers. +** Change these definitions if no predefined LUA_FLOAT_* / LUA_INT_* +** satisfy your needs. +** =================================================================== +*/ + +/* +@@ LUA_NUMBER is the floating-point type used by Lua. +@@ LUAI_UACNUMBER is the result of a 'default argument promotion' +@@ over a floating number. +@@ l_mathlim(x) corrects limit name 'x' to the proper float type +** by prefixing it with one of FLT/DBL/LDBL. +@@ LUA_NUMBER_FRMLEN is the length modifier for writing floats. +@@ LUA_NUMBER_FMT is the format for writing floats. +@@ lua_number2str converts a float to a string. +@@ l_mathop allows the addition of an 'l' or 'f' to all math operations. +@@ l_floor takes the floor of a float. +@@ lua_str2number converts a decimal numeric string to a number. +*/ + + +/* The following definitions are good for most cases here */ + +#define l_floor(x) (l_mathop(floor)(x)) + +#define lua_number2str(s,sz,n) \ + l_sprintf((s), sz, LUA_NUMBER_FMT, (LUAI_UACNUMBER)(n)) + +/* +@@ lua_numbertointeger converts a float number to an integer, or +** returns 0 if float is not within the range of a lua_Integer. +** (The range comparisons are tricky because of rounding. The tests +** here assume a two-complement representation, where MININTEGER always +** has an exact representation as a float; MAXINTEGER may not have one, +** and therefore its conversion to float may have an ill-defined value.) +*/ +#define lua_numbertointeger(n,p) \ + ((n) >= (LUA_NUMBER)(LUA_MININTEGER) && \ + (n) < -(LUA_NUMBER)(LUA_MININTEGER) && \ + (*(p) = (LUA_INTEGER)(n), 1)) + + +/* now the variable definitions */ + +#if LUA_FLOAT_TYPE == LUA_FLOAT_FLOAT /* { single float */ + +#define LUA_NUMBER float + +#define l_mathlim(n) (FLT_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.7g" + +#define l_mathop(op) op##f + +#define lua_str2number(s,p) strtof((s), (p)) + + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE /* }{ long double */ + +#define LUA_NUMBER long double + +#define l_mathlim(n) (LDBL_##n) + +#define LUAI_UACNUMBER long double + +#define LUA_NUMBER_FRMLEN "L" +#define LUA_NUMBER_FMT "%.19Lg" + +#define l_mathop(op) op##l + +#define lua_str2number(s,p) strtold((s), (p)) + +#elif LUA_FLOAT_TYPE == LUA_FLOAT_DOUBLE /* }{ double */ + +#define LUA_NUMBER double + +#define l_mathlim(n) (DBL_##n) + +#define LUAI_UACNUMBER double + +#define LUA_NUMBER_FRMLEN "" +#define LUA_NUMBER_FMT "%.14g" + +#define l_mathop(op) op + +#define lua_str2number(s,p) strtod((s), (p)) + +#else /* }{ */ + +#error "numeric float type not defined" + +#endif /* } */ + + + +/* +@@ LUA_INTEGER is the integer type used by Lua. +** +@@ LUA_UNSIGNED is the unsigned version of LUA_INTEGER. +** +@@ LUAI_UACINT is the result of a 'default argument promotion' +@@ over a lUA_INTEGER. +@@ LUA_INTEGER_FRMLEN is the length modifier for reading/writing integers. +@@ LUA_INTEGER_FMT is the format for writing integers. +@@ LUA_MAXINTEGER is the maximum value for a LUA_INTEGER. +@@ LUA_MININTEGER is the minimum value for a LUA_INTEGER. +@@ lua_integer2str converts an integer to a string. +*/ + + +/* The following definitions are good for most cases here */ + +#define LUA_INTEGER_FMT "%" LUA_INTEGER_FRMLEN "d" + +#define LUAI_UACINT LUA_INTEGER + +#define lua_integer2str(s,sz,n) \ + l_sprintf((s), sz, LUA_INTEGER_FMT, (LUAI_UACINT)(n)) + +/* +** use LUAI_UACINT here to avoid problems with promotions (which +** can turn a comparison between unsigneds into a signed comparison) +*/ +#define LUA_UNSIGNED unsigned LUAI_UACINT + + +/* now the variable definitions */ + +#if LUA_INT_TYPE == LUA_INT_INT /* { int */ + +#define LUA_INTEGER int +#define LUA_INTEGER_FRMLEN "" + +#define LUA_MAXINTEGER INT_MAX +#define LUA_MININTEGER INT_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONG /* }{ long */ + +#define LUA_INTEGER long +#define LUA_INTEGER_FRMLEN "l" + +#define LUA_MAXINTEGER LONG_MAX +#define LUA_MININTEGER LONG_MIN + +#elif LUA_INT_TYPE == LUA_INT_LONGLONG /* }{ long long */ + +/* use presence of macro LLONG_MAX as proxy for C99 compliance */ +#if defined(LLONG_MAX) /* { */ +/* use ISO C99 stuff */ + +#define LUA_INTEGER long long +#define LUA_INTEGER_FRMLEN "ll" + +#define LUA_MAXINTEGER LLONG_MAX +#define LUA_MININTEGER LLONG_MIN + +#elif defined(LUA_USE_WINDOWS) /* }{ */ +/* in Windows, can use specific Windows types */ + +#define LUA_INTEGER __int64 +#define LUA_INTEGER_FRMLEN "I64" + +#define LUA_MAXINTEGER _I64_MAX +#define LUA_MININTEGER _I64_MIN + +#else /* }{ */ + +#error "Compiler does not support 'long long'. Use option '-DLUA_32BITS' \ + or '-DLUA_C89_NUMBERS' (see file 'luaconf.h' for details)" + +#endif /* } */ + +#else /* }{ */ + +#error "numeric integer type not defined" + +#endif /* } */ + +/* }================================================================== */ + + +/* +** {================================================================== +** Dependencies with C99 and other C details +** =================================================================== +*/ + +/* +@@ l_sprintf is equivalent to 'snprintf' or 'sprintf' in C89. +** (All uses in Lua have only one format item.) +*/ +#if !defined(LUA_USE_C89) +#define l_sprintf(s,sz,f,i) snprintf(s,sz,f,i) +#else +#define l_sprintf(s,sz,f,i) ((void)(sz), sprintf(s,f,i)) +#endif + + +/* +@@ lua_strx2number converts an hexadecimal numeric string to a number. +** In C99, 'strtod' does that conversion. Otherwise, you can +** leave 'lua_strx2number' undefined and Lua will provide its own +** implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_strx2number(s,p) lua_str2number(s,p) +#endif + + +/* +@@ lua_pointer2str converts a pointer to a readable string in a +** non-specified way. +*/ +#define lua_pointer2str(buff,sz,p) l_sprintf(buff,sz,"%p",p) + + +/* +@@ lua_number2strx converts a float to an hexadecimal numeric string. +** In C99, 'sprintf' (with format specifiers '%a'/'%A') does that. +** Otherwise, you can leave 'lua_number2strx' undefined and Lua will +** provide its own implementation. +*/ +#if !defined(LUA_USE_C89) +#define lua_number2strx(L,b,sz,f,n) \ + ((void)L, l_sprintf(b,sz,f,(LUAI_UACNUMBER)(n))) +#endif + + +/* +** 'strtof' and 'opf' variants for math functions are not valid in +** C89. Otherwise, the macro 'HUGE_VALF' is a good proxy for testing the +** availability of these variants. ('math.h' is already included in +** all files that use these macros.) +*/ +#if defined(LUA_USE_C89) || (defined(HUGE_VAL) && !defined(HUGE_VALF)) +#undef l_mathop /* variants not available */ +#undef lua_str2number +#define l_mathop(op) (lua_Number)op /* no variant */ +#define lua_str2number(s,p) ((lua_Number)strtod((s), (p))) +#endif + + +/* +@@ LUA_KCONTEXT is the type of the context ('ctx') for continuation +** functions. It must be a numerical type; Lua will use 'intptr_t' if +** available, otherwise it will use 'ptrdiff_t' (the nearest thing to +** 'intptr_t' in C89) +*/ +#define LUA_KCONTEXT ptrdiff_t + +#if !defined(LUA_USE_C89) && defined(__STDC_VERSION__) && \ + __STDC_VERSION__ >= 199901L +#include +#if defined(INTPTR_MAX) /* even in C99 this type is optional */ +#undef LUA_KCONTEXT +#define LUA_KCONTEXT intptr_t +#endif +#endif + + +/* +@@ lua_getlocaledecpoint gets the locale "radix character" (decimal point). +** Change that if you do not want to use C locales. (Code using this +** macro must include header 'locale.h'.) +*/ +#if !defined(lua_getlocaledecpoint) +#define lua_getlocaledecpoint() (localeconv()->decimal_point[0]) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Language Variations +** ===================================================================== +*/ + +/* +@@ LUA_NOCVTN2S/LUA_NOCVTS2N control how Lua performs some +** coercions. Define LUA_NOCVTN2S to turn off automatic coercion from +** numbers to strings. Define LUA_NOCVTS2N to turn off automatic +** coercion from strings to numbers. +*/ +/* #define LUA_NOCVTN2S */ +/* #define LUA_NOCVTS2N */ + + +/* +@@ LUA_USE_APICHECK turns on several consistency checks on the C API. +** Define it as a help when debugging C code. +*/ +#if defined(LUA_USE_APICHECK) +#include +#define luai_apicheck(l,e) assert(e) +#endif + +/* }================================================================== */ + + +/* +** {================================================================== +** Macros that affect the API and must be stable (that is, must be the +** same when you compile Lua and when you compile code that links to +** Lua). You probably do not want/need to change them. +** ===================================================================== +*/ + +/* +@@ LUAI_MAXSTACK limits the size of the Lua stack. +** CHANGE it if you need a different limit. This limit is arbitrary; +** its only purpose is to stop Lua from consuming unlimited stack +** space (and to reserve some numbers for pseudo-indices). +*/ +#if LUAI_BITSINT >= 32 +#define LUAI_MAXSTACK 1000000 +#else +#define LUAI_MAXSTACK 15000 +#endif + + +/* +@@ LUA_EXTRASPACE defines the size of a raw memory area associated with +** a Lua state with very fast access. +** CHANGE it if you need a different size. +*/ +#define LUA_EXTRASPACE (sizeof(void *)) + + +/* +@@ LUA_IDSIZE gives the maximum size for the description of the source +@@ of a function in debug information. +** CHANGE it if you want a different size. +*/ +#define LUA_IDSIZE 60 + + +/* +@@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. +** CHANGE it if it uses too much C-stack space. (For long double, +** 'string.format("%.99f", -1e4932)' needs 5034 bytes, so a +** smaller buffer would force a memory allocation for each call to +** 'string.format'.) +*/ +#if LUA_FLOAT_TYPE == LUA_FLOAT_LONGDOUBLE +#define LUAL_BUFFERSIZE 8192 +#else +#define LUAL_BUFFERSIZE ((int)(0x80 * sizeof(void*) * sizeof(lua_Integer))) +#endif + +/* }================================================================== */ + + +/* +@@ LUA_QL describes how error messages quote program elements. +** Lua does not use these macros anymore; they are here for +** compatibility only. +*/ +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") + + + + +/* =================================================================== */ + +/* +** Local configuration. You can use this space to add your redefinitions +** without modifying the main part of the file. +*/ + + + + + +#endif + diff --git a/src/lua/lualib.h b/src/lua/lualib.h new file mode 100644 index 000000000000..f5304aa0dd0a --- /dev/null +++ b/src/lua/lualib.h @@ -0,0 +1,61 @@ +/* +** $Id: lualib.h,v 1.45.1.1 2017/04/19 17:20:42 roberto Exp $ +** Lua standard libraries +** See Copyright Notice in lua.h +*/ + + +#ifndef lualib_h +#define lualib_h + +#include "lua.h" + + +/* version suffix for environment variable names */ +#define LUA_VERSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + + +LUAMOD_API int (luaopen_base) (lua_State *L); + +#define LUA_COLIBNAME "coroutine" +LUAMOD_API int (luaopen_coroutine) (lua_State *L); + +#define LUA_TABLIBNAME "table" +LUAMOD_API int (luaopen_table) (lua_State *L); + +#define LUA_IOLIBNAME "io" +LUAMOD_API int (luaopen_io) (lua_State *L); + +#define LUA_OSLIBNAME "os" +LUAMOD_API int (luaopen_os) (lua_State *L); + +#define LUA_STRLIBNAME "string" +LUAMOD_API int (luaopen_string) (lua_State *L); + +#define LUA_UTF8LIBNAME "utf8" +LUAMOD_API int (luaopen_utf8) (lua_State *L); + +#define LUA_BITLIBNAME "bit32" +LUAMOD_API int (luaopen_bit32) (lua_State *L); + +#define LUA_MATHLIBNAME "math" +LUAMOD_API int (luaopen_math) (lua_State *L); + +#define LUA_DBLIBNAME "debug" +LUAMOD_API int (luaopen_debug) (lua_State *L); + +#define LUA_LOADLIBNAME "package" +LUAMOD_API int (luaopen_package) (lua_State *L); + + +/* open all previous libraries */ +LUALIB_API void (luaL_openlibs) (lua_State *L); + + + +#if !defined(lua_assert) +#define lua_assert(x) ((void)0) +#endif + + +#endif diff --git a/src/lua/lundump.c b/src/lua/lundump.c new file mode 100644 index 000000000000..938388785178 --- /dev/null +++ b/src/lua/lundump.c @@ -0,0 +1,287 @@ +/* +** $Id: lundump.c,v 2.44.1.1 2017/04/19 17:20:42 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#define lundump_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lmem.h" +#include "lobject.h" +#include "lstring.h" +#include "lundump.h" +#include "lzio.h" + + +#if !defined(luai_verifycode) +#define luai_verifycode(L,b,f) /* empty */ +#endif + + +typedef struct { + lua_State *L; + ZIO *Z; + const char *name; +} LoadState; + + +static l_noret error(LoadState *S, const char *why) { + luaO_pushfstring(S->L, "%s: %s precompiled chunk", S->name, why); + luaD_throw(S->L, LUA_ERRSYNTAX); +} + + +/* +** All high-level loads go through LoadVector; you can change it to +** adapt to the endianness of the input +*/ +#define LoadVector(S,b,n) LoadBlock(S,b,(n)*sizeof((b)[0])) + +static void LoadBlock (LoadState *S, void *b, size_t size) { + if (luaZ_read(S->Z, b, size) != 0) + error(S, "truncated"); +} + + +#define LoadVar(S,x) LoadVector(S,&x,1) + + +static lu_byte LoadByte (LoadState *S) { + lu_byte x; + LoadVar(S, x); + return x; +} + + +static int LoadInt (LoadState *S) { + int x; + LoadVar(S, x); + return x; +} + + +static lua_Number LoadNumber (LoadState *S) { + lua_Number x; + LoadVar(S, x); + return x; +} + + +static lua_Integer LoadInteger (LoadState *S) { + lua_Integer x; + LoadVar(S, x); + return x; +} + + +static TString *LoadString (LoadState *S, Proto *p) { + lua_State *L = S->L; + size_t size = LoadByte(S); + TString *ts; + if (size == 0xFF) + LoadVar(S, size); + if (size == 0) + return NULL; + else if (--size <= LUAI_MAXSHORTLEN) { /* short string? */ + char buff[LUAI_MAXSHORTLEN]; + LoadVector(S, buff, size); + ts = luaS_newlstr(L, buff, size); + } + else { /* long string */ + ts = luaS_createlngstrobj(L, size); + setsvalue2s(L, L->top, ts); /* anchor it ('loadVector' can GC) */ + luaD_inctop(L); + LoadVector(S, getstr(ts), size); /* load directly in final place */ + L->top--; /* pop string */ + } + luaC_objbarrier(L, p, ts); + return ts; +} + + +static void LoadCode (LoadState *S, Proto *f) { + int n = LoadInt(S); + f->code = luaM_newvector(S->L, n, Instruction); + f->sizecode = n; + LoadVector(S, f->code, n); +} + + +static void LoadFunction(LoadState *S, Proto *f, TString *psource); + + +static void LoadConstants (LoadState *S, Proto *f) { + int i; + int n = LoadInt(S); + f->k = luaM_newvector(S->L, n, TValue); + f->sizek = n; + for (i = 0; i < n; i++) + setnilvalue(&f->k[i]); + for (i = 0; i < n; i++) { + TValue *o = &f->k[i]; + int t = LoadByte(S); + switch (t) { + case LUA_TNIL: + setnilvalue(o); + break; + case LUA_TBOOLEAN: + setbvalue(o, LoadByte(S)); + break; + case LUA_TNUMFLT: + setfltvalue(o, LoadNumber(S)); + break; + case LUA_TNUMINT: + setivalue(o, LoadInteger(S)); + break; + case LUA_TSHRSTR: + case LUA_TLNGSTR: + setsvalue2n(S->L, o, LoadString(S, f)); + break; + default: + lua_assert(0); + } + } +} + + +static void LoadProtos (LoadState *S, Proto *f) { + int i; + int n = LoadInt(S); + f->p = luaM_newvector(S->L, n, Proto *); + f->sizep = n; + for (i = 0; i < n; i++) + f->p[i] = NULL; + for (i = 0; i < n; i++) { + f->p[i] = luaF_newproto(S->L); + luaC_objbarrier(S->L, f, f->p[i]); + LoadFunction(S, f->p[i], f->source); + } +} + + +static void LoadUpvalues (LoadState *S, Proto *f) { + int i, n; + n = LoadInt(S); + f->upvalues = luaM_newvector(S->L, n, Upvaldesc); + f->sizeupvalues = n; + for (i = 0; i < n; i++) + f->upvalues[i].name = NULL; + for (i = 0; i < n; i++) { + f->upvalues[i].instack = LoadByte(S); + f->upvalues[i].idx = LoadByte(S); + } +} + + +static void LoadDebug (LoadState *S, Proto *f) { + int i, n; + n = LoadInt(S); + f->lineinfo = luaM_newvector(S->L, n, int); + f->sizelineinfo = n; + LoadVector(S, f->lineinfo, n); + n = LoadInt(S); + f->locvars = luaM_newvector(S->L, n, LocVar); + f->sizelocvars = n; + for (i = 0; i < n; i++) + f->locvars[i].varname = NULL; + for (i = 0; i < n; i++) { + f->locvars[i].varname = LoadString(S, f); + f->locvars[i].startpc = LoadInt(S); + f->locvars[i].endpc = LoadInt(S); + } + n = LoadInt(S); + for (i = 0; i < n; i++) + f->upvalues[i].name = LoadString(S, f); +} + + +static void LoadFunction (LoadState *S, Proto *f, TString *psource) { + f->source = LoadString(S, f); + if (f->source == NULL) /* no source in dump? */ + f->source = psource; /* reuse parent's source */ + f->linedefined = LoadInt(S); + f->lastlinedefined = LoadInt(S); + f->numparams = LoadByte(S); + f->is_vararg = LoadByte(S); + f->maxstacksize = LoadByte(S); + LoadCode(S, f); + LoadConstants(S, f); + LoadUpvalues(S, f); + LoadProtos(S, f); + LoadDebug(S, f); +} + + +static void checkliteral (LoadState *S, const char *s, const char *msg) { + char buff[sizeof(LUA_SIGNATURE) + sizeof(LUAC_DATA)]; /* larger than both */ + size_t len = strlen(s); + LoadVector(S, buff, len); + if (memcmp(s, buff, len) != 0) + error(S, msg); +} + + +static void fchecksize (LoadState *S, size_t size, const char *tname) { + if (LoadByte(S) != size) + error(S, luaO_pushfstring(S->L, "%s size mismatch in", tname)); +} + + +#define checksize(S,t) fchecksize(S,sizeof(t),#t) + +static void checkHeader (LoadState *S) { + checkliteral(S, &LUA_SIGNATURE[1], "not a"); /* 1st char already checked */ + if (LoadByte(S) != LUAC_VERSION) + error(S, "version mismatch in"); + if (LoadByte(S) != LUAC_FORMAT) + error(S, "format mismatch in"); + checkliteral(S, LUAC_DATA, "corrupted"); + checksize(S, int); + checksize(S, size_t); + checksize(S, Instruction); + checksize(S, lua_Integer); + checksize(S, lua_Number); + if (LoadInteger(S) != LUAC_INT) + error(S, "endianness mismatch in"); + if (LoadNumber(S) != LUAC_NUM) + error(S, "float format mismatch in"); +} + + +/* +** load precompiled chunk +*/ +LClosure *luaU_undump(lua_State *L, ZIO *Z, const char *name) { + LoadState S; + LClosure *cl; + if (*name == '@' || *name == '=') + S.name = name + 1; + else if (*name == LUA_SIGNATURE[0]) + S.name = "binary string"; + else + S.name = name; + S.L = L; + S.Z = Z; + checkHeader(&S); + cl = luaF_newLclosure(L, LoadByte(&S)); + setclLvalue(L, L->top, cl); + luaD_inctop(L); + cl->p = luaF_newproto(L); + luaC_objbarrier(L, cl, cl->p); + LoadFunction(&S, cl->p, NULL); + lua_assert(cl->nupvalues == cl->p->sizeupvalues); + luai_verifycode(L, buff, cl->p); + return cl; +} + diff --git a/src/lua/lundump.h b/src/lua/lundump.h new file mode 100644 index 000000000000..ce492d689cd1 --- /dev/null +++ b/src/lua/lundump.h @@ -0,0 +1,32 @@ +/* +** $Id: lundump.h,v 1.45.1.1 2017/04/19 17:20:42 roberto Exp $ +** load precompiled Lua chunks +** See Copyright Notice in lua.h +*/ + +#ifndef lundump_h +#define lundump_h + +#include "llimits.h" +#include "lobject.h" +#include "lzio.h" + + +/* data to catch conversion errors */ +#define LUAC_DATA "\x19\x93\r\n\x1a\n" + +#define LUAC_INT 0x5678 +#define LUAC_NUM cast_num(370.5) + +#define MYINT(s) (s[0]-'0') +#define LUAC_VERSION (MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR)) +#define LUAC_FORMAT 0 /* this is the official format */ + +/* load one chunk; from lundump.c */ +LUAI_FUNC LClosure* luaU_undump (lua_State* L, ZIO* Z, const char* name); + +/* dump one chunk; from ldump.c */ +LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, + void* data, int strip); + +#endif diff --git a/src/lua/lutf8lib.c b/src/lua/lutf8lib.c new file mode 100644 index 000000000000..10bd238a71de --- /dev/null +++ b/src/lua/lutf8lib.c @@ -0,0 +1,256 @@ +/* +** $Id: lutf8lib.c,v 1.16.1.1 2017/04/19 17:29:57 roberto Exp $ +** Standard library for UTF-8 manipulation +** See Copyright Notice in lua.h +*/ + +#define lutf8lib_c +#define LUA_LIB + +#include "lprefix.h" + + +#include +#include +#include +#include + +#include "lua.h" + +#include "lauxlib.h" +#include "lualib.h" + +#define MAXUNICODE 0x10FFFF + +#define iscont(p) ((*(p) & 0xC0) == 0x80) + + +/* from strlib */ +/* translate a relative string position: negative means back from end */ +static lua_Integer u_posrelat (lua_Integer pos, size_t len) { + if (pos >= 0) return pos; + else if (0u - (size_t)pos > len) return 0; + else return (lua_Integer)len + pos + 1; +} + + +/* +** Decode one UTF-8 sequence, returning NULL if byte sequence is invalid. +*/ +static const char *utf8_decode (const char *o, int *val) { + static const unsigned int limits[] = {0xFF, 0x7F, 0x7FF, 0xFFFF}; + const unsigned char *s = (const unsigned char *)o; + unsigned int c = s[0]; + unsigned int res = 0; /* final result */ + if (c < 0x80) /* ascii? */ + res = c; + else { + int count = 0; /* to count number of continuation bytes */ + while (c & 0x40) { /* still have continuation bytes? */ + int cc = s[++count]; /* read next byte */ + if ((cc & 0xC0) != 0x80) /* not a continuation byte? */ + return NULL; /* invalid byte sequence */ + res = (res << 6) | (cc & 0x3F); /* add lower 6 bits from cont. byte */ + c <<= 1; /* to test next bit */ + } + res |= ((c & 0x7F) << (count * 5)); /* add first byte */ + if (count > 3 || res > MAXUNICODE || res <= limits[count]) + return NULL; /* invalid byte sequence */ + s += count; /* skip continuation bytes read */ + } + if (val) *val = res; + return (const char *)s + 1; /* +1 to include first byte */ +} + + +/* +** utf8len(s [, i [, j]]) --> number of characters that start in the +** range [i,j], or nil + current position if 's' is not well formed in +** that interval +*/ +static int utflen (lua_State *L) { + int n = 0; + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer posj = u_posrelat(luaL_optinteger(L, 3, -1), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 2, + "initial position out of string"); + luaL_argcheck(L, --posj < (lua_Integer)len, 3, + "final position out of string"); + while (posi <= posj) { + const char *s1 = utf8_decode(s + posi, NULL); + if (s1 == NULL) { /* conversion error? */ + lua_pushnil(L); /* return nil ... */ + lua_pushinteger(L, posi + 1); /* ... and current position */ + return 2; + } + posi = s1 - s; + n++; + } + lua_pushinteger(L, n); + return 1; +} + + +/* +** codepoint(s, [i, [j]]) -> returns codepoints for all characters +** that start in the range [i,j] +*/ +static int codepoint (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer posi = u_posrelat(luaL_optinteger(L, 2, 1), len); + lua_Integer pose = u_posrelat(luaL_optinteger(L, 3, posi), len); + int n; + const char *se; + luaL_argcheck(L, posi >= 1, 2, "out of range"); + luaL_argcheck(L, pose <= (lua_Integer)len, 3, "out of range"); + if (posi > pose) return 0; /* empty interval; return no values */ + if (pose - posi >= INT_MAX) /* (lua_Integer -> int) overflow? */ + return luaL_error(L, "string slice too long"); + n = (int)(pose - posi) + 1; + luaL_checkstack(L, n, "string slice too long"); + n = 0; + se = s + pose; + for (s += posi - 1; s < se;) { + int code; + s = utf8_decode(s, &code); + if (s == NULL) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, code); + n++; + } + return n; +} + + +static void pushutfchar (lua_State *L, int arg) { + lua_Integer code = luaL_checkinteger(L, arg); + luaL_argcheck(L, 0 <= code && code <= MAXUNICODE, arg, "value out of range"); + lua_pushfstring(L, "%U", (long)code); +} + + +/* +** utfchar(n1, n2, ...) -> char(n1)..char(n2)... +*/ +static int utfchar (lua_State *L) { + int n = lua_gettop(L); /* number of arguments */ + if (n == 1) /* optimize common case of single char */ + pushutfchar(L, 1); + else { + int i; + luaL_Buffer b; + luaL_buffinit(L, &b); + for (i = 1; i <= n; i++) { + pushutfchar(L, i); + luaL_addvalue(&b); + } + luaL_pushresult(&b); + } + return 1; +} + + +/* +** offset(s, n, [i]) -> index where n-th character counting from +** position 'i' starts; 0 means character at 'i'. +*/ +static int byteoffset (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = luaL_checkinteger(L, 2); + lua_Integer posi = (n >= 0) ? 1 : len + 1; + posi = u_posrelat(luaL_optinteger(L, 3, posi), len); + luaL_argcheck(L, 1 <= posi && --posi <= (lua_Integer)len, 3, + "position out of range"); + if (n == 0) { + /* find beginning of current byte sequence */ + while (posi > 0 && iscont(s + posi)) posi--; + } + else { + if (iscont(s + posi)) + return luaL_error(L, "initial position is a continuation byte"); + if (n < 0) { + while (n < 0 && posi > 0) { /* move back */ + do { /* find beginning of previous character */ + posi--; + } while (posi > 0 && iscont(s + posi)); + n++; + } + } + else { + n--; /* do not move for 1st character */ + while (n > 0 && posi < (lua_Integer)len) { + do { /* find beginning of next character */ + posi++; + } while (iscont(s + posi)); /* (cannot pass final '\0') */ + n--; + } + } + } + if (n == 0) /* did it find given character? */ + lua_pushinteger(L, posi + 1); + else /* no such character */ + lua_pushnil(L); + return 1; +} + + +static int iter_aux (lua_State *L) { + size_t len; + const char *s = luaL_checklstring(L, 1, &len); + lua_Integer n = lua_tointeger(L, 2) - 1; + if (n < 0) /* first iteration? */ + n = 0; /* start from here */ + else if (n < (lua_Integer)len) { + n++; /* skip current byte */ + while (iscont(s + n)) n++; /* and its continuations */ + } + if (n >= (lua_Integer)len) + return 0; /* no more codepoints */ + else { + int code; + const char *next = utf8_decode(s + n, &code); + if (next == NULL || iscont(next)) + return luaL_error(L, "invalid UTF-8 code"); + lua_pushinteger(L, n + 1); + lua_pushinteger(L, code); + return 2; + } +} + + +static int iter_codes (lua_State *L) { + luaL_checkstring(L, 1); + lua_pushcfunction(L, iter_aux); + lua_pushvalue(L, 1); + lua_pushinteger(L, 0); + return 3; +} + + +/* pattern to match a single UTF-8 character */ +#define UTF8PATT "[\0-\x7F\xC2-\xF4][\x80-\xBF]*" + + +static const luaL_Reg funcs[] = { + {"offset", byteoffset}, + {"codepoint", codepoint}, + {"char", utfchar}, + {"len", utflen}, + {"codes", iter_codes}, + /* placeholders */ + {"charpattern", NULL}, + {NULL, NULL} +}; + + +LUAMOD_API int luaopen_utf8 (lua_State *L) { + luaL_newlib(L, funcs); + lua_pushlstring(L, UTF8PATT, sizeof(UTF8PATT)/sizeof(char) - 1); + lua_setfield(L, -2, "charpattern"); + return 1; +} + diff --git a/src/lua/lvm.c b/src/lua/lvm.c new file mode 100644 index 000000000000..cc43d8714db0 --- /dev/null +++ b/src/lua/lvm.c @@ -0,0 +1,1322 @@ +/* +** $Id: lvm.c,v 2.268.1.1 2017/04/19 17:39:34 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#define lvm_c +#define LUA_CORE + +#include "lprefix.h" + +#include +#include +#include +#include +#include +#include + +#include "lua.h" + +#include "ldebug.h" +#include "ldo.h" +#include "lfunc.h" +#include "lgc.h" +#include "lobject.h" +#include "lopcodes.h" +#include "lstate.h" +#include "lstring.h" +#include "ltable.h" +#include "ltm.h" +#include "lvm.h" + + +/* limit for table tag-method chains (to avoid loops) */ +#define MAXTAGLOOP 2000 + + + +/* +** 'l_intfitsf' checks whether a given integer can be converted to a +** float without rounding. Used in comparisons. Left undefined if +** all integers fit in a float precisely. +*/ +#if !defined(l_intfitsf) + +/* number of bits in the mantissa of a float */ +#define NBM (l_mathlim(MANT_DIG)) + +/* +** Check whether some integers may not fit in a float, that is, whether +** (maxinteger >> NBM) > 0 (that implies (1 << NBM) <= maxinteger). +** (The shifts are done in parts to avoid shifting by more than the size +** of an integer. In a worst case, NBM == 113 for long double and +** sizeof(integer) == 32.) +*/ +#if ((((LUA_MAXINTEGER >> (NBM / 4)) >> (NBM / 4)) >> (NBM / 4)) \ + >> (NBM - (3 * (NBM / 4)))) > 0 + +#define l_intfitsf(i) \ + (-((lua_Integer)1 << NBM) <= (i) && (i) <= ((lua_Integer)1 << NBM)) + +#endif + +#endif + + + +/* +** Try to convert a value to a float. The float case is already handled +** by the macro 'tonumber'. +*/ +int luaV_tonumber_ (const TValue *obj, lua_Number *n) { + TValue v; + if (ttisinteger(obj)) { + *n = cast_num(ivalue(obj)); + return 1; + } + else if (cvt2num(obj) && /* string convertible to number? */ + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { + *n = nvalue(&v); /* convert result of 'luaO_str2num' to a float */ + return 1; + } + else + return 0; /* conversion failed */ +} + + +/* +** try to convert a value to an integer, rounding according to 'mode': +** mode == 0: accepts only integral values +** mode == 1: takes the floor of the number +** mode == 2: takes the ceil of the number +*/ +int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode) { + TValue v; + again: + if (ttisfloat(obj)) { + lua_Number n = fltvalue(obj); + lua_Number f = l_floor(n); + if (n != f) { /* not an integral value? */ + if (mode == 0) return 0; /* fails if mode demands integral value */ + else if (mode > 1) /* needs ceil? */ + f += 1; /* convert floor to ceil (remember: n != f) */ + } + return lua_numbertointeger(f, p); + } + else if (ttisinteger(obj)) { + *p = ivalue(obj); + return 1; + } + else if (cvt2num(obj) && + luaO_str2num(svalue(obj), &v) == vslen(obj) + 1) { + obj = &v; + goto again; /* convert result from 'luaO_str2num' to an integer */ + } + return 0; /* conversion failed */ +} + + +/* +** Try to convert a 'for' limit to an integer, preserving the +** semantics of the loop. +** (The following explanation assumes a non-negative step; it is valid +** for negative steps mutatis mutandis.) +** If the limit can be converted to an integer, rounding down, that is +** it. +** Otherwise, check whether the limit can be converted to a number. If +** the number is too large, it is OK to set the limit as LUA_MAXINTEGER, +** which means no limit. If the number is too negative, the loop +** should not run, because any initial integer value is larger than the +** limit. So, it sets the limit to LUA_MININTEGER. 'stopnow' corrects +** the extreme case when the initial value is LUA_MININTEGER, in which +** case the LUA_MININTEGER limit would still run the loop once. +*/ +static int forlimit (const TValue *obj, lua_Integer *p, lua_Integer step, + int *stopnow) { + *stopnow = 0; /* usually, let loops run */ + if (!luaV_tointeger(obj, p, (step < 0 ? 2 : 1))) { /* not fit in integer? */ + lua_Number n; /* try to convert to float */ + if (!tonumber(obj, &n)) /* cannot convert to float? */ + return 0; /* not a number */ + if (luai_numlt(0, n)) { /* if true, float is larger than max integer */ + *p = LUA_MAXINTEGER; + if (step < 0) *stopnow = 1; + } + else { /* float is smaller than min integer */ + *p = LUA_MININTEGER; + if (step >= 0) *stopnow = 1; + } + } + return 1; +} + + +/* +** Finish the table access 'val = t[key]'. +** if 'slot' is NULL, 't' is not a table; otherwise, 'slot' points to +** t[k] entry (which must be nil). +*/ +void luaV_finishget (lua_State *L, const TValue *t, TValue *key, StkId val, + const TValue *slot) { + int loop; /* counter to avoid infinite loops */ + const TValue *tm; /* metamethod */ + for (loop = 0; loop < MAXTAGLOOP; loop++) { + if (slot == NULL) { /* 't' is not a table? */ + lua_assert(!ttistable(t)); + tm = luaT_gettmbyobj(L, t, TM_INDEX); + if (ttisnil(tm)) + luaG_typeerror(L, t, "index"); /* no metamethod */ + /* else will try the metamethod */ + } + else { /* 't' is a table */ + lua_assert(ttisnil(slot)); + tm = fasttm(L, hvalue(t)->metatable, TM_INDEX); /* table's metamethod */ + if (tm == NULL) { /* no metamethod? */ + setnilvalue(val); /* result is nil */ + return; + } + /* else will try the metamethod */ + } + if (ttisfunction(tm)) { /* is metamethod a function? */ + luaT_callTM(L, tm, t, key, val, 1); /* call it */ + return; + } + t = tm; /* else try to access 'tm[key]' */ + if (luaV_fastget(L,t,key,slot,luaH_get)) { /* fast track? */ + setobj2s(L, val, slot); /* done */ + return; + } + /* else repeat (tail call 'luaV_finishget') */ + } + luaG_runerror(L, "'__index' chain too long; possible loop"); +} + + +/* +** Finish a table assignment 't[key] = val'. +** If 'slot' is NULL, 't' is not a table. Otherwise, 'slot' points +** to the entry 't[key]', or to 'luaO_nilobject' if there is no such +** entry. (The value at 'slot' must be nil, otherwise 'luaV_fastset' +** would have done the job.) +*/ +void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *slot) { + int loop; /* counter to avoid infinite loops */ + for (loop = 0; loop < MAXTAGLOOP; loop++) { + const TValue *tm; /* '__newindex' metamethod */ + if (slot != NULL) { /* is 't' a table? */ + Table *h = hvalue(t); /* save 't' table */ + lua_assert(ttisnil(slot)); /* old value must be nil */ + tm = fasttm(L, h->metatable, TM_NEWINDEX); /* get metamethod */ + if (tm == NULL) { /* no metamethod? */ + if (slot == luaO_nilobject) /* no previous entry? */ + slot = luaH_newkey(L, h, key); /* create one */ + /* no metamethod and (now) there is an entry with given key */ + setobj2t(L, cast(TValue *, slot), val); /* set its new value */ + invalidateTMcache(h); + luaC_barrierback(L, h, val); + return; + } + /* else will try the metamethod */ + } + else { /* not a table; check metamethod */ + if (ttisnil(tm = luaT_gettmbyobj(L, t, TM_NEWINDEX))) + luaG_typeerror(L, t, "index"); + } + /* try the metamethod */ + if (ttisfunction(tm)) { + luaT_callTM(L, tm, t, key, val, 0); + return; + } + t = tm; /* else repeat assignment over 'tm' */ + if (luaV_fastset(L, t, key, slot, luaH_get, val)) + return; /* done */ + /* else loop */ + } + luaG_runerror(L, "'__newindex' chain too long; possible loop"); +} + + +/* +** Compare two strings 'ls' x 'rs', returning an integer smaller-equal- +** -larger than zero if 'ls' is smaller-equal-larger than 'rs'. +** The code is a little tricky because it allows '\0' in the strings +** and it uses 'strcoll' (to respect locales) for each segments +** of the strings. +*/ +static int l_strcmp (const TString *ls, const TString *rs) { + const char *l = getstr(ls); + size_t ll = tsslen(ls); + const char *r = getstr(rs); + size_t lr = tsslen(rs); + for (;;) { /* for each segment */ + int temp = strcoll(l, r); + if (temp != 0) /* not equal? */ + return temp; /* done */ + else { /* strings are equal up to a '\0' */ + size_t len = strlen(l); /* index of first '\0' in both strings */ + if (len == lr) /* 'rs' is finished? */ + return (len == ll) ? 0 : 1; /* check 'ls' */ + else if (len == ll) /* 'ls' is finished? */ + return -1; /* 'ls' is smaller than 'rs' ('rs' is not finished) */ + /* both strings longer than 'len'; go on comparing after the '\0' */ + len++; + l += len; ll -= len; r += len; lr -= len; + } + } +} + + +/* +** Check whether integer 'i' is less than float 'f'. If 'i' has an +** exact representation as a float ('l_intfitsf'), compare numbers as +** floats. Otherwise, if 'f' is outside the range for integers, result +** is trivial. Otherwise, compare them as integers. (When 'i' has no +** float representation, either 'f' is "far away" from 'i' or 'f' has +** no precision left for a fractional part; either way, how 'f' is +** truncated is irrelevant.) When 'f' is NaN, comparisons must result +** in false. +*/ +static int LTintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f > cast_num(LUA_MININTEGER)) /* minint < f <= maxint ? */ + return (i < cast(lua_Integer, f)); /* compare them as integers */ + else /* f <= minint <= i (or 'f' is NaN) --> not(i < f) */ + return 0; + } +#endif + return luai_numlt(cast_num(i), f); /* compare them as floats */ +} + + +/* +** Check whether integer 'i' is less than or equal to float 'f'. +** See comments on previous function. +*/ +static int LEintfloat (lua_Integer i, lua_Number f) { +#if defined(l_intfitsf) + if (!l_intfitsf(i)) { + if (f >= -cast_num(LUA_MININTEGER)) /* -minint == maxint + 1 */ + return 1; /* f >= maxint + 1 > i */ + else if (f >= cast_num(LUA_MININTEGER)) /* minint <= f <= maxint ? */ + return (i <= cast(lua_Integer, f)); /* compare them as integers */ + else /* f < minint <= i (or 'f' is NaN) --> not(i <= f) */ + return 0; + } +#endif + return luai_numle(cast_num(i), f); /* compare them as floats */ +} + + +/* +** Return 'l < r', for numbers. +*/ +static int LTnum (const TValue *l, const TValue *r) { + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li < ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LTintfloat(li, fltvalue(r)); /* l < r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numlt(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN < i is always false */ + else /* without NaN, (l < r) <--> not(r <= l) */ + return !LEintfloat(ivalue(r), lf); /* not (r <= l) ? */ + } +} + + +/* +** Return 'l <= r', for numbers. +*/ +static int LEnum (const TValue *l, const TValue *r) { + if (ttisinteger(l)) { + lua_Integer li = ivalue(l); + if (ttisinteger(r)) + return li <= ivalue(r); /* both are integers */ + else /* 'l' is int and 'r' is float */ + return LEintfloat(li, fltvalue(r)); /* l <= r ? */ + } + else { + lua_Number lf = fltvalue(l); /* 'l' must be float */ + if (ttisfloat(r)) + return luai_numle(lf, fltvalue(r)); /* both are float */ + else if (luai_numisnan(lf)) /* 'r' is int and 'l' is float */ + return 0; /* NaN <= i is always false */ + else /* without NaN, (l <= r) <--> not(r < l) */ + return !LTintfloat(ivalue(r), lf); /* not (r < l) ? */ + } +} + + +/* +** Main operation less than; return 'l < r'. +*/ +int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r) { + int res; + if (ttisnumber(l) && ttisnumber(r)) /* both operands are numbers? */ + return LTnum(l, r); + else if (ttisstring(l) && ttisstring(r)) /* both are strings? */ + return l_strcmp(tsvalue(l), tsvalue(r)) < 0; + else if ((res = luaT_callorderTM(L, l, r, TM_LT)) < 0) /* no metamethod? */ + luaG_ordererror(L, l, r); /* error */ + return res; +} + + +/* +** Main operation less than or equal to; return 'l <= r'. If it needs +** a metamethod and there is no '__le', try '__lt', based on +** l <= r iff !(r < l) (assuming a total order). If the metamethod +** yields during this substitution, the continuation has to know +** about it (to negate the result of r= 0) /* try 'le' */ + return res; + else { /* try 'lt': */ + L->ci->callstatus |= CIST_LEQ; /* mark it is doing 'lt' for 'le' */ + res = luaT_callorderTM(L, r, l, TM_LT); + L->ci->callstatus ^= CIST_LEQ; /* clear mark */ + if (res < 0) + luaG_ordererror(L, l, r); + return !res; /* result is negated */ + } +} + + +/* +** Main operation for equality of Lua values; return 't1 == t2'. +** L == NULL means raw equality (no metamethods) +*/ +int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2) { + const TValue *tm; + if (ttype(t1) != ttype(t2)) { /* not the same variant? */ + if (ttnov(t1) != ttnov(t2) || ttnov(t1) != LUA_TNUMBER) + return 0; /* only numbers can be equal with different variants */ + else { /* two numbers with different variants */ + lua_Integer i1, i2; /* compare them as integers */ + return (tointeger(t1, &i1) && tointeger(t2, &i2) && i1 == i2); + } + } + /* values have same type and same variant */ + switch (ttype(t1)) { + case LUA_TNIL: return 1; + case LUA_TNUMINT: return (ivalue(t1) == ivalue(t2)); + case LUA_TNUMFLT: return luai_numeq(fltvalue(t1), fltvalue(t2)); + case LUA_TBOOLEAN: return bvalue(t1) == bvalue(t2); /* true must be 1 !! */ + case LUA_TLIGHTUSERDATA: return pvalue(t1) == pvalue(t2); + case LUA_TLCF: return fvalue(t1) == fvalue(t2); + case LUA_TSHRSTR: return eqshrstr(tsvalue(t1), tsvalue(t2)); + case LUA_TLNGSTR: return luaS_eqlngstr(tsvalue(t1), tsvalue(t2)); + case LUA_TUSERDATA: { + if (uvalue(t1) == uvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = fasttm(L, uvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, uvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + case LUA_TTABLE: { + if (hvalue(t1) == hvalue(t2)) return 1; + else if (L == NULL) return 0; + tm = fasttm(L, hvalue(t1)->metatable, TM_EQ); + if (tm == NULL) + tm = fasttm(L, hvalue(t2)->metatable, TM_EQ); + break; /* will try TM */ + } + default: + return gcvalue(t1) == gcvalue(t2); + } + if (tm == NULL) /* no TM? */ + return 0; /* objects are different */ + luaT_callTM(L, tm, t1, t2, L->top, 1); /* call TM */ + return !l_isfalse(L->top); +} + + +/* macro used by 'luaV_concat' to ensure that element at 'o' is a string */ +#define tostring(L,o) \ + (ttisstring(o) || (cvt2str(o) && (luaO_tostring(L, o), 1))) + +#define isemptystr(o) (ttisshrstring(o) && tsvalue(o)->shrlen == 0) + +/* copy strings in stack from top - n up to top - 1 to buffer */ +static void copy2buff (StkId top, int n, char *buff) { + size_t tl = 0; /* size already copied */ + do { + size_t l = vslen(top - n); /* length of string being copied */ + memcpy(buff + tl, svalue(top - n), l * sizeof(char)); + tl += l; + } while (--n > 0); +} + + +/* +** Main operation for concatenation: concat 'total' values in the stack, +** from 'L->top - total' up to 'L->top - 1'. +*/ +void luaV_concat (lua_State *L, int total) { + lua_assert(total >= 2); + do { + StkId top = L->top; + int n = 2; /* number of elements handled in this pass (at least 2) */ + if (!(ttisstring(top-2) || cvt2str(top-2)) || !tostring(L, top-1)) + luaT_trybinTM(L, top-2, top-1, top-2, TM_CONCAT); + else if (isemptystr(top - 1)) /* second operand is empty? */ + cast_void(tostring(L, top - 2)); /* result is first operand */ + else if (isemptystr(top - 2)) { /* first operand is an empty string? */ + setobjs2s(L, top - 2, top - 1); /* result is second op. */ + } + else { + /* at least two non-empty string values; get as many as possible */ + size_t tl = vslen(top - 1); + TString *ts; + /* collect total length and number of strings */ + for (n = 1; n < total && tostring(L, top - n - 1); n++) { + size_t l = vslen(top - n - 1); + if (l >= (MAX_SIZE/sizeof(char)) - tl) + luaG_runerror(L, "string length overflow"); + tl += l; + } + if (tl <= LUAI_MAXSHORTLEN) { /* is result a short string? */ + char buff[LUAI_MAXSHORTLEN]; + copy2buff(top, n, buff); /* copy strings to buffer */ + ts = luaS_newlstr(L, buff, tl); + } + else { /* long string; copy strings directly to final result */ + ts = luaS_createlngstrobj(L, tl); + copy2buff(top, n, getstr(ts)); + } + setsvalue2s(L, top - n, ts); /* create result */ + } + total -= n-1; /* got 'n' strings to create 1 new */ + L->top -= n-1; /* popped 'n' strings and pushed one */ + } while (total > 1); /* repeat until only 1 result left */ +} + + +/* +** Main operation 'ra' = #rb'. +*/ +void luaV_objlen (lua_State *L, StkId ra, const TValue *rb) { + const TValue *tm; + switch (ttype(rb)) { + case LUA_TTABLE: { + Table *h = hvalue(rb); + tm = fasttm(L, h->metatable, TM_LEN); + if (tm) break; /* metamethod? break switch to call it */ + setivalue(ra, luaH_getn(h)); /* else primitive len */ + return; + } + case LUA_TSHRSTR: { + setivalue(ra, tsvalue(rb)->shrlen); + return; + } + case LUA_TLNGSTR: { + setivalue(ra, tsvalue(rb)->u.lnglen); + return; + } + default: { /* try metamethod */ + tm = luaT_gettmbyobj(L, rb, TM_LEN); + if (ttisnil(tm)) /* no metamethod? */ + luaG_typeerror(L, rb, "get length of"); + break; + } + } + luaT_callTM(L, tm, rb, rb, ra, 1); +} + + +/* +** Integer division; return 'm // n', that is, floor(m/n). +** C division truncates its result (rounds towards zero). +** 'floor(q) == trunc(q)' when 'q >= 0' or when 'q' is integer, +** otherwise 'floor(q) == trunc(q) - 1'. +*/ +lua_Integer luaV_div (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to divide by zero"); + return intop(-, 0, m); /* n==-1; avoid overflow with 0x80000...//-1 */ + } + else { + lua_Integer q = m / n; /* perform C division */ + if ((m ^ n) < 0 && m % n != 0) /* 'm/n' would be negative non-integer? */ + q -= 1; /* correct result for different rounding */ + return q; + } +} + + +/* +** Integer modulus; return 'm % n'. (Assume that C '%' with +** negative operands follows C99 behavior. See previous comment +** about luaV_div.) +*/ +lua_Integer luaV_mod (lua_State *L, lua_Integer m, lua_Integer n) { + if (l_castS2U(n) + 1u <= 1u) { /* special cases: -1 or 0 */ + if (n == 0) + luaG_runerror(L, "attempt to perform 'n%%0'"); + return 0; /* m % -1 == 0; avoid overflow with 0x80000...%-1 */ + } + else { + lua_Integer r = m % n; + if (r != 0 && (m ^ n) < 0) /* 'm/n' would be non-integer negative? */ + r += n; /* correct result for different rounding */ + return r; + } +} + + +/* number of bits in an integer */ +#define NBITS cast_int(sizeof(lua_Integer) * CHAR_BIT) + +/* +** Shift left operation. (Shift right just negates 'y'.) +*/ +lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y) { + if (y < 0) { /* shift right? */ + if (y <= -NBITS) return 0; + else return intop(>>, x, -y); + } + else { /* shift left */ + if (y >= NBITS) return 0; + else return intop(<<, x, y); + } +} + + +/* +** check whether cached closure in prototype 'p' may be reused, that is, +** whether there is a cached closure with the same upvalues needed by +** new closure to be created. +*/ +static LClosure *getcached (Proto *p, UpVal **encup, StkId base) { + LClosure *c = p->cache; + if (c != NULL) { /* is there a cached closure? */ + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + for (i = 0; i < nup; i++) { /* check whether it has right upvalues */ + TValue *v = uv[i].instack ? base + uv[i].idx : encup[uv[i].idx]->v; + if (c->upvals[i]->v != v) + return NULL; /* wrong upvalue; cannot reuse closure */ + } + } + return c; /* return cached closure (or NULL if no cached closure) */ +} + + +/* +** create a new Lua closure, push it in the stack, and initialize +** its upvalues. Note that the closure is not cached if prototype is +** already black (which means that 'cache' was already cleared by the +** GC). +*/ +static void pushclosure (lua_State *L, Proto *p, UpVal **encup, StkId base, + StkId ra) { + int nup = p->sizeupvalues; + Upvaldesc *uv = p->upvalues; + int i; + LClosure *ncl = luaF_newLclosure(L, nup); + ncl->p = p; + setclLvalue(L, ra, ncl); /* anchor new closure in stack */ + for (i = 0; i < nup; i++) { /* fill in its upvalues */ + if (uv[i].instack) /* upvalue refers to local variable? */ + ncl->upvals[i] = luaF_findupval(L, base + uv[i].idx); + else /* get upvalue from enclosing function */ + ncl->upvals[i] = encup[uv[i].idx]; + ncl->upvals[i]->refcount++; + /* new closure is white, so we do not need a barrier here */ + } + if (!isblack(p)) /* cache will not break GC invariant? */ + p->cache = ncl; /* save it on cache for reuse */ +} + + +/* +** finish execution of an opcode interrupted by an yield +*/ +void luaV_finishOp (lua_State *L) { + CallInfo *ci = L->ci; + StkId base = ci->u.l.base; + Instruction inst = *(ci->u.l.savedpc - 1); /* interrupted instruction */ + OpCode op = GET_OPCODE(inst); + switch (op) { /* finish its execution */ + case OP_ADD: case OP_SUB: case OP_MUL: case OP_DIV: case OP_IDIV: + case OP_BAND: case OP_BOR: case OP_BXOR: case OP_SHL: case OP_SHR: + case OP_MOD: case OP_POW: + case OP_UNM: case OP_BNOT: case OP_LEN: + case OP_GETTABUP: case OP_GETTABLE: case OP_SELF: { + setobjs2s(L, base + GETARG_A(inst), --L->top); + break; + } + case OP_LE: case OP_LT: case OP_EQ: { + int res = !l_isfalse(L->top - 1); + L->top--; + if (ci->callstatus & CIST_LEQ) { /* "<=" using "<" instead? */ + lua_assert(op == OP_LE); + ci->callstatus ^= CIST_LEQ; /* clear mark */ + res = !res; /* negate result */ + } + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_JMP); + if (res != GETARG_A(inst)) /* condition failed? */ + ci->u.l.savedpc++; /* skip jump instruction */ + break; + } + case OP_CONCAT: { + StkId top = L->top - 1; /* top when 'luaT_trybinTM' was called */ + int b = GETARG_B(inst); /* first element to concatenate */ + int total = cast_int(top - 1 - (base + b)); /* yet to concatenate */ + setobj2s(L, top - 2, top); /* put TM result in proper position */ + if (total > 1) { /* are there elements to concat? */ + L->top = top - 1; /* top is one after last element (at top-2) */ + luaV_concat(L, total); /* concat them (may yield again) */ + } + /* move final result to final position */ + setobj2s(L, ci->u.l.base + GETARG_A(inst), L->top - 1); + L->top = ci->top; /* restore top */ + break; + } + case OP_TFORCALL: { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_TFORLOOP); + L->top = ci->top; /* correct top */ + break; + } + case OP_CALL: { + if (GETARG_C(inst) - 1 >= 0) /* nresults >= 0? */ + L->top = ci->top; /* adjust results */ + break; + } + case OP_TAILCALL: case OP_SETTABUP: case OP_SETTABLE: + break; + default: lua_assert(0); + } +} + + + + +/* +** {================================================================== +** Function 'luaV_execute': main interpreter loop +** =================================================================== +*/ + + +/* +** some macros for common tasks in 'luaV_execute' +*/ + + +#define RA(i) (base+GETARG_A(i)) +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) + + +/* execute a jump instruction */ +#define dojump(ci,i,e) \ + { int a = GETARG_A(i); \ + if (a != 0) luaF_close(L, ci->u.l.base + a - 1); \ + ci->u.l.savedpc += GETARG_sBx(i) + e; } + +/* for test instructions, execute the jump instruction that follows it */ +#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } + + +#define Protect(x) { {x;}; base = ci->u.l.base; } + +#define checkGC(L,c) \ + { luaC_condGC(L, L->top = (c), /* limit of live values */ \ + Protect(L->top = ci->top)); /* restore top */ \ + luai_threadyield(L); } + + +/* fetch an instruction and prepare its execution */ +#define vmfetch() { \ + i = *(ci->u.l.savedpc++); \ + if (L->hookmask & (LUA_MASKLINE | LUA_MASKCOUNT)) \ + Protect(luaG_traceexec(L)); \ + ra = RA(i); /* WARNING: any stack reallocation invalidates 'ra' */ \ + lua_assert(base == ci->u.l.base); \ + lua_assert(base <= L->top && L->top < L->stack + L->stacksize); \ +} + +#define vmdispatch(o) switch(o) +#define vmcase(l) case l: +#define vmbreak break + + +/* +** copy of 'luaV_gettable', but protecting the call to potential +** metamethod (which can reallocate the stack) +*/ +#define gettableProtected(L,t,k,v) { const TValue *slot; \ + if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ + else Protect(luaV_finishget(L,t,k,v,slot)); } + + +/* same for 'luaV_settable' */ +#define settableProtected(L,t,k,v) { const TValue *slot; \ + if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ + Protect(luaV_finishset(L,t,k,v,slot)); } + + + +void luaV_execute (lua_State *L) { + CallInfo *ci = L->ci; + LClosure *cl; + TValue *k; + StkId base; + ci->callstatus |= CIST_FRESH; /* fresh invocation of 'luaV_execute" */ + newframe: /* reentry point when frame changes (call/return) */ + lua_assert(ci == L->ci); + cl = clLvalue(ci->func); /* local reference to function's closure */ + k = cl->p->k; /* local reference to function's constant table */ + base = ci->u.l.base; /* local copy of function's base */ + /* main loop of interpreter */ + for (;;) { + Instruction i; + StkId ra; + vmfetch(); + vmdispatch (GET_OPCODE(i)) { + vmcase(OP_MOVE) { + setobjs2s(L, ra, RB(i)); + vmbreak; + } + vmcase(OP_LOADK) { + TValue *rb = k + GETARG_Bx(i); + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADKX) { + TValue *rb; + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + rb = k + GETARG_Ax(*ci->u.l.savedpc++); + setobj2s(L, ra, rb); + vmbreak; + } + vmcase(OP_LOADBOOL) { + setbvalue(ra, GETARG_B(i)); + if (GETARG_C(i)) ci->u.l.savedpc++; /* skip next instruction (if C) */ + vmbreak; + } + vmcase(OP_LOADNIL) { + int b = GETARG_B(i); + do { + setnilvalue(ra++); + } while (b--); + vmbreak; + } + vmcase(OP_GETUPVAL) { + int b = GETARG_B(i); + setobj2s(L, ra, cl->upvals[b]->v); + vmbreak; + } + vmcase(OP_GETTABUP) { + TValue *upval = cl->upvals[GETARG_B(i)]->v; + TValue *rc = RKC(i); + gettableProtected(L, upval, rc, ra); + vmbreak; + } + vmcase(OP_GETTABLE) { + StkId rb = RB(i); + TValue *rc = RKC(i); + gettableProtected(L, rb, rc, ra); + vmbreak; + } + vmcase(OP_SETTABUP) { + TValue *upval = cl->upvals[GETARG_A(i)]->v; + TValue *rb = RKB(i); + TValue *rc = RKC(i); + settableProtected(L, upval, rb, rc); + vmbreak; + } + vmcase(OP_SETUPVAL) { + UpVal *uv = cl->upvals[GETARG_B(i)]; + setobj(L, uv->v, ra); + luaC_upvalbarrier(L, uv); + vmbreak; + } + vmcase(OP_SETTABLE) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + settableProtected(L, ra, rb, rc); + vmbreak; + } + vmcase(OP_NEWTABLE) { + int b = GETARG_B(i); + int c = GETARG_C(i); + Table *t = luaH_new(L); + sethvalue(L, ra, t); + if (b != 0 || c != 0) + luaH_resize(L, t, luaO_fb2int(b), luaO_fb2int(c)); + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_SELF) { + const TValue *aux; + StkId rb = RB(i); + TValue *rc = RKC(i); + TString *key = tsvalue(rc); /* key must be a string */ + setobjs2s(L, ra + 1, rb); + if (luaV_fastget(L, rb, key, aux, luaH_getstr)) { + setobj2s(L, ra, aux); + } + else Protect(luaV_finishget(L, rb, rc, ra, aux)); + vmbreak; + } + vmcase(OP_ADD) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(+, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numadd(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_ADD)); } + vmbreak; + } + vmcase(OP_SUB) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(-, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numsub(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SUB)); } + vmbreak; + } + vmcase(OP_MUL) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, intop(*, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_nummul(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MUL)); } + vmbreak; + } + vmcase(OP_DIV) { /* float division (always with floats) */ + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numdiv(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_DIV)); } + vmbreak; + } + vmcase(OP_BAND) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, intop(&, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BAND)); } + vmbreak; + } + vmcase(OP_BOR) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, intop(|, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BOR)); } + vmbreak; + } + vmcase(OP_BXOR) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, intop(^, ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_BXOR)); } + vmbreak; + } + vmcase(OP_SHL) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, luaV_shiftl(ib, ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHL)); } + vmbreak; + } + vmcase(OP_SHR) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Integer ib; lua_Integer ic; + if (tointeger(rb, &ib) && tointeger(rc, &ic)) { + setivalue(ra, luaV_shiftl(ib, -ic)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_SHR)); } + vmbreak; + } + vmcase(OP_MOD) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_mod(L, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + lua_Number m; + luai_nummod(L, nb, nc, m); + setfltvalue(ra, m); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_MOD)); } + vmbreak; + } + vmcase(OP_IDIV) { /* floor division */ + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (ttisinteger(rb) && ttisinteger(rc)) { + lua_Integer ib = ivalue(rb); lua_Integer ic = ivalue(rc); + setivalue(ra, luaV_div(L, ib, ic)); + } + else if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numidiv(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_IDIV)); } + vmbreak; + } + vmcase(OP_POW) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + lua_Number nb; lua_Number nc; + if (tonumber(rb, &nb) && tonumber(rc, &nc)) { + setfltvalue(ra, luai_numpow(L, nb, nc)); + } + else { Protect(luaT_trybinTM(L, rb, rc, ra, TM_POW)); } + vmbreak; + } + vmcase(OP_UNM) { + TValue *rb = RB(i); + lua_Number nb; + if (ttisinteger(rb)) { + lua_Integer ib = ivalue(rb); + setivalue(ra, intop(-, 0, ib)); + } + else if (tonumber(rb, &nb)) { + setfltvalue(ra, luai_numunm(L, nb)); + } + else { + Protect(luaT_trybinTM(L, rb, rb, ra, TM_UNM)); + } + vmbreak; + } + vmcase(OP_BNOT) { + TValue *rb = RB(i); + lua_Integer ib; + if (tointeger(rb, &ib)) { + setivalue(ra, intop(^, ~l_castS2U(0), ib)); + } + else { + Protect(luaT_trybinTM(L, rb, rb, ra, TM_BNOT)); + } + vmbreak; + } + vmcase(OP_NOT) { + TValue *rb = RB(i); + int res = l_isfalse(rb); /* next assignment may change this value */ + setbvalue(ra, res); + vmbreak; + } + vmcase(OP_LEN) { + Protect(luaV_objlen(L, ra, RB(i))); + vmbreak; + } + vmcase(OP_CONCAT) { + int b = GETARG_B(i); + int c = GETARG_C(i); + StkId rb; + L->top = base + c + 1; /* mark the end of concat operands */ + Protect(luaV_concat(L, c - b + 1)); + ra = RA(i); /* 'luaV_concat' may invoke TMs and move the stack */ + rb = base + b; + setobjs2s(L, ra, rb); + checkGC(L, (ra >= rb ? ra + 1 : rb)); + L->top = ci->top; /* restore top */ + vmbreak; + } + vmcase(OP_JMP) { + dojump(ci, i, 0); + vmbreak; + } + vmcase(OP_EQ) { + TValue *rb = RKB(i); + TValue *rc = RKC(i); + Protect( + if (luaV_equalobj(L, rb, rc) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmbreak; + } + vmcase(OP_LT) { + Protect( + if (luaV_lessthan(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmbreak; + } + vmcase(OP_LE) { + Protect( + if (luaV_lessequal(L, RKB(i), RKC(i)) != GETARG_A(i)) + ci->u.l.savedpc++; + else + donextjump(ci); + ) + vmbreak; + } + vmcase(OP_TEST) { + if (GETARG_C(i) ? l_isfalse(ra) : !l_isfalse(ra)) + ci->u.l.savedpc++; + else + donextjump(ci); + vmbreak; + } + vmcase(OP_TESTSET) { + TValue *rb = RB(i); + if (GETARG_C(i) ? l_isfalse(rb) : !l_isfalse(rb)) + ci->u.l.savedpc++; + else { + setobjs2s(L, ra, rb); + donextjump(ci); + } + vmbreak; + } + vmcase(OP_CALL) { + int b = GETARG_B(i); + int nresults = GETARG_C(i) - 1; + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + if (luaD_precall(L, ra, nresults)) { /* C function? */ + if (nresults >= 0) + L->top = ci->top; /* adjust results */ + Protect((void)0); /* update 'base' */ + } + else { /* Lua function */ + ci = L->ci; + goto newframe; /* restart luaV_execute over new Lua function */ + } + vmbreak; + } + vmcase(OP_TAILCALL) { + int b = GETARG_B(i); + if (b != 0) L->top = ra+b; /* else previous instruction set top */ + lua_assert(GETARG_C(i) - 1 == LUA_MULTRET); + if (luaD_precall(L, ra, LUA_MULTRET)) { /* C function? */ + Protect((void)0); /* update 'base' */ + } + else { + /* tail call: put called frame (n) in place of caller one (o) */ + CallInfo *nci = L->ci; /* called frame */ + CallInfo *oci = nci->previous; /* caller frame */ + StkId nfunc = nci->func; /* called function */ + StkId ofunc = oci->func; /* caller function */ + /* last stack slot filled by 'precall' */ + StkId lim = nci->u.l.base + getproto(nfunc)->numparams; + int aux; + /* close all upvalues from previous call */ + if (cl->p->sizep > 0) luaF_close(L, oci->u.l.base); + /* move new frame into old one */ + for (aux = 0; nfunc + aux < lim; aux++) + setobjs2s(L, ofunc + aux, nfunc + aux); + oci->u.l.base = ofunc + (nci->u.l.base - nfunc); /* correct base */ + oci->top = L->top = ofunc + (L->top - nfunc); /* correct top */ + oci->u.l.savedpc = nci->u.l.savedpc; + oci->callstatus |= CIST_TAIL; /* function was tail called */ + ci = L->ci = oci; /* remove new frame */ + lua_assert(L->top == oci->u.l.base + getproto(ofunc)->maxstacksize); + goto newframe; /* restart luaV_execute over new Lua function */ + } + vmbreak; + } + vmcase(OP_RETURN) { + int b = GETARG_B(i); + if (cl->p->sizep > 0) luaF_close(L, base); + b = luaD_poscall(L, ci, ra, (b != 0 ? b - 1 : cast_int(L->top - ra))); + if (ci->callstatus & CIST_FRESH) /* local 'ci' still from callee */ + return; /* external invocation: return */ + else { /* invocation via reentry: continue execution */ + ci = L->ci; + if (b) L->top = ci->top; + lua_assert(isLua(ci)); + lua_assert(GET_OPCODE(*((ci)->u.l.savedpc - 1)) == OP_CALL); + goto newframe; /* restart luaV_execute over new Lua function */ + } + } + vmcase(OP_FORLOOP) { + if (ttisinteger(ra)) { /* integer loop? */ + lua_Integer step = ivalue(ra + 2); + lua_Integer idx = intop(+, ivalue(ra), step); /* increment index */ + lua_Integer limit = ivalue(ra + 1); + if ((0 < step) ? (idx <= limit) : (limit <= idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + chgivalue(ra, idx); /* update internal index... */ + setivalue(ra + 3, idx); /* ...and external index */ + } + } + else { /* floating loop */ + lua_Number step = fltvalue(ra + 2); + lua_Number idx = luai_numadd(L, fltvalue(ra), step); /* inc. index */ + lua_Number limit = fltvalue(ra + 1); + if (luai_numlt(0, step) ? luai_numle(idx, limit) + : luai_numle(limit, idx)) { + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + chgfltvalue(ra, idx); /* update internal index... */ + setfltvalue(ra + 3, idx); /* ...and external index */ + } + } + vmbreak; + } + vmcase(OP_FORPREP) { + TValue *init = ra; + TValue *plimit = ra + 1; + TValue *pstep = ra + 2; + lua_Integer ilimit; + int stopnow; + if (ttisinteger(init) && ttisinteger(pstep) && + forlimit(plimit, &ilimit, ivalue(pstep), &stopnow)) { + /* all values are integer */ + lua_Integer initv = (stopnow ? 0 : ivalue(init)); + setivalue(plimit, ilimit); + setivalue(init, intop(-, initv, ivalue(pstep))); + } + else { /* try making all values floats */ + lua_Number ninit; lua_Number nlimit; lua_Number nstep; + if (!tonumber(plimit, &nlimit)) + luaG_runerror(L, "'for' limit must be a number"); + setfltvalue(plimit, nlimit); + if (!tonumber(pstep, &nstep)) + luaG_runerror(L, "'for' step must be a number"); + setfltvalue(pstep, nstep); + if (!tonumber(init, &ninit)) + luaG_runerror(L, "'for' initial value must be a number"); + setfltvalue(init, luai_numsub(L, ninit, nstep)); + } + ci->u.l.savedpc += GETARG_sBx(i); + vmbreak; + } + vmcase(OP_TFORCALL) { + StkId cb = ra + 3; /* call base */ + setobjs2s(L, cb+2, ra+2); + setobjs2s(L, cb+1, ra+1); + setobjs2s(L, cb, ra); + L->top = cb + 3; /* func. + 2 args (state and index) */ + Protect(luaD_call(L, cb, GETARG_C(i))); + L->top = ci->top; + i = *(ci->u.l.savedpc++); /* go to next instruction */ + ra = RA(i); + lua_assert(GET_OPCODE(i) == OP_TFORLOOP); + goto l_tforloop; + } + vmcase(OP_TFORLOOP) { + l_tforloop: + if (!ttisnil(ra + 1)) { /* continue loop? */ + setobjs2s(L, ra, ra + 1); /* save control variable */ + ci->u.l.savedpc += GETARG_sBx(i); /* jump back */ + } + vmbreak; + } + vmcase(OP_SETLIST) { + int n = GETARG_B(i); + int c = GETARG_C(i); + unsigned int last; + Table *h; + if (n == 0) n = cast_int(L->top - ra) - 1; + if (c == 0) { + lua_assert(GET_OPCODE(*ci->u.l.savedpc) == OP_EXTRAARG); + c = GETARG_Ax(*ci->u.l.savedpc++); + } + h = hvalue(ra); + last = ((c-1)*LFIELDS_PER_FLUSH) + n; + if (last > h->sizearray) /* needs more space? */ + luaH_resizearray(L, h, last); /* preallocate it at once */ + for (; n > 0; n--) { + TValue *val = ra+n; + luaH_setint(L, h, last--, val); + luaC_barrierback(L, h, val); + } + L->top = ci->top; /* correct top (in case of previous open call) */ + vmbreak; + } + vmcase(OP_CLOSURE) { + Proto *p = cl->p->p[GETARG_Bx(i)]; + LClosure *ncl = getcached(p, cl->upvals, base); /* cached closure */ + if (ncl == NULL) /* no match? */ + pushclosure(L, p, cl->upvals, base, ra); /* create a new one */ + else + setclLvalue(L, ra, ncl); /* push cashed closure */ + checkGC(L, ra + 1); + vmbreak; + } + vmcase(OP_VARARG) { + int b = GETARG_B(i) - 1; /* required results */ + int j; + int n = cast_int(base - ci->func) - cl->p->numparams - 1; + if (n < 0) /* less arguments than parameters? */ + n = 0; /* no vararg arguments */ + if (b < 0) { /* B == 0? */ + b = n; /* get all var. arguments */ + Protect(luaD_checkstack(L, n)); + ra = RA(i); /* previous call may change the stack */ + L->top = ra + n; + } + for (j = 0; j < b && j < n; j++) + setobjs2s(L, ra + j, base - n + j); + for (; j < b; j++) /* complete required results with nil */ + setnilvalue(ra + j); + vmbreak; + } + vmcase(OP_EXTRAARG) { + lua_assert(0); + vmbreak; + } + } + } +} + +/* }================================================================== */ + diff --git a/src/lua/lvm.h b/src/lua/lvm.h new file mode 100644 index 000000000000..a8f954f04ce8 --- /dev/null +++ b/src/lua/lvm.h @@ -0,0 +1,113 @@ +/* +** $Id: lvm.h,v 2.41.1.1 2017/04/19 17:20:42 roberto Exp $ +** Lua virtual machine +** See Copyright Notice in lua.h +*/ + +#ifndef lvm_h +#define lvm_h + + +#include "ldo.h" +#include "lobject.h" +#include "ltm.h" + + +#if !defined(LUA_NOCVTN2S) +#define cvt2str(o) ttisnumber(o) +#else +#define cvt2str(o) 0 /* no conversion from numbers to strings */ +#endif + + +#if !defined(LUA_NOCVTS2N) +#define cvt2num(o) ttisstring(o) +#else +#define cvt2num(o) 0 /* no conversion from strings to numbers */ +#endif + + +/* +** You can define LUA_FLOORN2I if you want to convert floats to integers +** by flooring them (instead of raising an error if they are not +** integral values) +*/ +#if !defined(LUA_FLOORN2I) +#define LUA_FLOORN2I 0 +#endif + + +#define tonumber(o,n) \ + (ttisfloat(o) ? (*(n) = fltvalue(o), 1) : luaV_tonumber_(o,n)) + +#define tointeger(o,i) \ + (ttisinteger(o) ? (*(i) = ivalue(o), 1) : luaV_tointeger(o,i,LUA_FLOORN2I)) + +#define intop(op,v1,v2) l_castU2S(l_castS2U(v1) op l_castS2U(v2)) + +#define luaV_rawequalobj(t1,t2) luaV_equalobj(NULL,t1,t2) + + +/* +** fast track for 'gettable': if 't' is a table and 't[k]' is not nil, +** return 1 with 'slot' pointing to 't[k]' (final result). Otherwise, +** return 0 (meaning it will have to check metamethod) with 'slot' +** pointing to a nil 't[k]' (if 't' is a table) or NULL (otherwise). +** 'f' is the raw get function to use. +*/ +#define luaV_fastget(L,t,k,slot,f) \ + (!ttistable(t) \ + ? (slot = NULL, 0) /* not a table; 'slot' is NULL and result is 0 */ \ + : (slot = f(hvalue(t), k), /* else, do raw access */ \ + !ttisnil(slot))) /* result not nil? */ + +/* +** standard implementation for 'gettable' +*/ +#define luaV_gettable(L,t,k,v) { const TValue *slot; \ + if (luaV_fastget(L,t,k,slot,luaH_get)) { setobj2s(L, v, slot); } \ + else luaV_finishget(L,t,k,v,slot); } + + +/* +** Fast track for set table. If 't' is a table and 't[k]' is not nil, +** call GC barrier, do a raw 't[k]=v', and return true; otherwise, +** return false with 'slot' equal to NULL (if 't' is not a table) or +** 'nil'. (This is needed by 'luaV_finishget'.) Note that, if the macro +** returns true, there is no need to 'invalidateTMcache', because the +** call is not creating a new entry. +*/ +#define luaV_fastset(L,t,k,slot,f,v) \ + (!ttistable(t) \ + ? (slot = NULL, 0) \ + : (slot = f(hvalue(t), k), \ + ttisnil(slot) ? 0 \ + : (luaC_barrierback(L, hvalue(t), v), \ + setobj2t(L, cast(TValue *,slot), v), \ + 1))) + + +#define luaV_settable(L,t,k,v) { const TValue *slot; \ + if (!luaV_fastset(L,t,k,slot,luaH_get,v)) \ + luaV_finishset(L,t,k,v,slot); } + + + +LUAI_FUNC int luaV_equalobj (lua_State *L, const TValue *t1, const TValue *t2); +LUAI_FUNC int luaV_lessthan (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_lessequal (lua_State *L, const TValue *l, const TValue *r); +LUAI_FUNC int luaV_tonumber_ (const TValue *obj, lua_Number *n); +LUAI_FUNC int luaV_tointeger (const TValue *obj, lua_Integer *p, int mode); +LUAI_FUNC void luaV_finishget (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *slot); +LUAI_FUNC void luaV_finishset (lua_State *L, const TValue *t, TValue *key, + StkId val, const TValue *slot); +LUAI_FUNC void luaV_finishOp (lua_State *L); +LUAI_FUNC void luaV_execute (lua_State *L); +LUAI_FUNC void luaV_concat (lua_State *L, int total); +LUAI_FUNC lua_Integer luaV_div (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_mod (lua_State *L, lua_Integer x, lua_Integer y); +LUAI_FUNC lua_Integer luaV_shiftl (lua_Integer x, lua_Integer y); +LUAI_FUNC void luaV_objlen (lua_State *L, StkId ra, const TValue *rb); + +#endif diff --git a/src/lua/lzio.c b/src/lua/lzio.c new file mode 100644 index 000000000000..6f79094410fb --- /dev/null +++ b/src/lua/lzio.c @@ -0,0 +1,68 @@ +/* +** $Id: lzio.c,v 1.37.1.1 2017/04/19 17:20:42 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + +#define lzio_c +#define LUA_CORE + +#include "lprefix.h" + + +#include + +#include "lua.h" + +#include "llimits.h" +#include "lmem.h" +#include "lstate.h" +#include "lzio.h" + + +int luaZ_fill (ZIO *z) { + size_t size; + lua_State *L = z->L; + const char *buff; + lua_unlock(L); + buff = z->reader(L, z->data, &size); + lua_lock(L); + if (buff == NULL || size == 0) + return EOZ; + z->n = size - 1; /* discount char being returned */ + z->p = buff; + return cast_uchar(*(z->p++)); +} + + +void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data) { + z->L = L; + z->reader = reader; + z->data = data; + z->n = 0; + z->p = NULL; +} + + +/* --------------------------------------------------------------- read --- */ +size_t luaZ_read (ZIO *z, void *b, size_t n) { + while (n) { + size_t m; + if (z->n == 0) { /* no bytes in buffer? */ + if (luaZ_fill(z) == EOZ) /* try to read more */ + return n; /* no more input; return number of missing bytes */ + else { + z->n++; /* luaZ_fill consumed first byte; put it back */ + z->p--; + } + } + m = (n <= z->n) ? n : z->n; /* min. between n and z->n */ + memcpy(b, z->p, m); + z->n -= m; + z->p += m; + b = (char *)b + m; + n -= m; + } + return 0; +} + diff --git a/src/lua/lzio.h b/src/lua/lzio.h new file mode 100644 index 000000000000..d8978708157d --- /dev/null +++ b/src/lua/lzio.h @@ -0,0 +1,66 @@ +/* +** $Id: lzio.h,v 1.31.1.1 2017/04/19 17:20:42 roberto Exp $ +** Buffered streams +** See Copyright Notice in lua.h +*/ + + +#ifndef lzio_h +#define lzio_h + +#include "lua.h" + +#include "lmem.h" + + +#define EOZ (-1) /* end of stream */ + +typedef struct Zio ZIO; + +#define zgetc(z) (((z)->n--)>0 ? cast_uchar(*(z)->p++) : luaZ_fill(z)) + + +typedef struct Mbuffer { + char *buffer; + size_t n; + size_t buffsize; +} Mbuffer; + +#define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) + +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) + +#define luaZ_buffremove(buff,i) ((buff)->n -= (i)) +#define luaZ_resetbuffer(buff) ((buff)->n = 0) + + +#define luaZ_resizebuffer(L, buff, size) \ + ((buff)->buffer = luaM_reallocvchar(L, (buff)->buffer, \ + (buff)->buffsize, size), \ + (buff)->buffsize = size) + +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) + + +LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, + void *data); +LUAI_FUNC size_t luaZ_read (ZIO* z, void *b, size_t n); /* read next n bytes */ + + + +/* --------- Private Part ------------------ */ + +struct Zio { + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; /* reader function */ + void *data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ +}; + + +LUAI_FUNC int luaZ_fill (ZIO *z); + +#endif diff --git a/src/main.cpp b/src/main.cpp index 5c5e3af1563c..aa36498dd81d 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -21,6 +21,7 @@ #else # include #endif +#include "catalua.h" #include "color.h" #include "crash.h" #include "cursesdef.h" @@ -193,6 +194,7 @@ int main( int argc, char *argv[] ) int seed = time( nullptr ); bool verifyexit = false; bool check_mods = false; + bool lua_doc_mode = false; std::string dump; dump_mode dmode = dump_mode::TSV; std::vector opts; @@ -237,7 +239,7 @@ int main( int argc, char *argv[] ) const char *section_default = nullptr; const char *section_map_sharing = "Map sharing"; const char *section_user_directory = "User directories"; - const std::array first_pass_arguments = {{ + const std::array first_pass_arguments = {{ { "--seed", "", "Sets the random number generator's seed value", @@ -415,6 +417,15 @@ int main( int argc, char *argv[] ) dont_debugmsg = true; return 0; } + }, + { + "--lua-doc", nullptr, + "If set, will generate Lua docs and exit", + section_default, + [&]( int, const char ** ) -> int { + lua_doc_mode = true; + return 0; + } } } }; @@ -649,6 +660,7 @@ int main( int argc, char *argv[] ) #if !defined(TILES) get_options().init(); get_options().load(); + get_options().save(); set_language(); // Have to set locale before initializing ncurses #endif @@ -718,6 +730,19 @@ int main( int argc, char *argv[] ) sigaction( SIGINT, &sigIntHandler, nullptr ); #endif + DebugLog( DL::Info, DC::Main ) << "LAPI version: " << cata::get_lapi_version_string(); + cata::startup_lua_test(); + + if( lua_doc_mode ) { + if( cata::generate_lua_docs() ) { + cata_printf( "Lua doc: Done!\n" ); + return 0; + } else { + cata_printf( "Lua doc: Failed.\n" ); + return 1; + } + } + prompt_select_lang_on_startup(); replay_buffered_debugmsg_prompts(); diff --git a/src/main_menu.cpp b/src/main_menu.cpp index c4c61ae08d2f..7636bce46e7b 100644 --- a/src/main_menu.cpp +++ b/src/main_menu.cpp @@ -16,6 +16,7 @@ #include "avatar.h" #include "cata_utility.h" #include "catacharset.h" +#include "catalua.h" #include "character_id.h" #include "color.h" #include "debug.h" @@ -217,12 +218,20 @@ void main_menu::display_sub_menu( int sel, const point &bottom_left, int sel_lin } std::vector all_worldnames = world_generator->all_worldnames(); for( int i = 0; static_cast( i ) < all_worldnames.size(); i++ ) { - int savegames_count = world_generator->get_world( all_worldnames[i] )->world_saves.size(); + WORLDPTR world = world_generator->get_world( all_worldnames[i] ); + int savegames_count = world->world_saves.size(); nc_color clr = c_white; + std::string txt = all_worldnames[i]; + if( world->needs_lua() && !cata::has_lua() ) { + clr = c_light_gray; + txt += " - "; + //~ Marker for worlds that need Lua in game builds without Lua + txt += _( "Needs Lua!" ); + } if( all_worldnames[i] == "TUTORIAL" || all_worldnames[i] == "DEFENSE" ) { clr = c_light_cyan; } - sub_opts.push_back( colorize( string_format( "%s (%d)", all_worldnames[i], savegames_count ), + sub_opts.push_back( colorize( string_format( "%s (%d)", txt, savegames_count ), ( sel2 == i + ( extra_opt ? 1 : 0 ) ) ? hilite( clr ) : clr ) ); int len = utf8_width( sub_opts.back(), true ); if( len > xlen ) { @@ -937,7 +946,8 @@ bool main_menu::new_character_tab() bool main_menu::load_character_tab( const std::string &worldname ) { - savegames = world_generator->get_world( worldname )->world_saves; + WORLDPTR world = world_generator->get_world( worldname ); + savegames = world->world_saves; if( MAP_SHARING::isSharing() ) { auto new_end = std::remove_if( savegames.begin(), savegames.end(), []( const save_t &str ) { return str.decoded_name() != MAP_SHARING::getUsername(); @@ -945,6 +955,14 @@ bool main_menu::load_character_tab( const std::string &worldname ) savegames.erase( new_end, savegames.end() ); } + if( world->needs_lua() && !cata::has_lua() ) { + on_error(); + //~ Error when attempting to load a world whose mods depend on Lua + //~ on game build that doesn't have Lua. %s = world name. + popup( _( "%s needs game build with Lua support!" ), worldname ); + return false; + } + if( savegames.empty() ) { on_error(); //~ %s = world name @@ -976,7 +994,6 @@ bool main_menu::load_character_tab( const std::string &worldname ) } ); g->gamemode = nullptr; - WORLDPTR world = world_generator->get_world( worldname ); world_generator->last_world_name = world->world_name; world_generator->last_character_name = savegames[opt_val].decoded_name(); world_generator->save_last_world_info(); diff --git a/src/map.cpp b/src/map.cpp index 4bb6a3d3d6bf..d1e55e93419d 100644 --- a/src/map.cpp +++ b/src/map.cpp @@ -5507,9 +5507,16 @@ int map::get_field_intensity( const tripoint &p, const field_type_id &type ) con return ( field_ptr == nullptr ? 0 : field_ptr->get_field_intensity() ); } + +bool map::has_field_at( const tripoint &p, bool check_bounds ) +{ + const tripoint sm = ms_to_sm_copy( p ); + return ( !check_bounds || inbounds( p ) ) && get_cache( p.z ).field_cache[sm.x + sm.y * MAPSIZE]; +} + field_entry *map::get_field( const tripoint &p, const field_type_id &type ) { - if( !inbounds( p ) ) { + if( !inbounds( p ) || !has_field_at( p, false ) ) { return nullptr; } diff --git a/src/map.h b/src/map.h index 0b0d96c578fe..ce2593e6378b 100644 --- a/src/map.h +++ b/src/map.h @@ -1434,6 +1434,11 @@ class map */ int set_field_intensity( const tripoint &p, const field_type_id &type, int new_intensity, bool isoffset = false ); + /** + * @return true if there **might** be a field at `p` + * @return false there's no fields at `p` + */ + bool has_field_at( const tripoint &p, bool check_bounds = true ); /** * Get field of specific type at point. * @return NULL if there is no such field entry at that place. diff --git a/src/mapdata.cpp b/src/mapdata.cpp index fd4ccb9820a2..67d295f47148 100644 --- a/src/mapdata.cpp +++ b/src/mapdata.cpp @@ -50,7 +50,7 @@ bool is_json_check_strict( const std::string &src ) /** @relates int_id */ template<> -inline bool int_id::is_valid() const +bool int_id::is_valid() const { return terrain_data.is_valid( *this ); } diff --git a/src/mapdata.h b/src/mapdata.h index d188c07b2bae..2cc1ccc24f8b 100644 --- a/src/mapdata.h +++ b/src/mapdata.h @@ -12,6 +12,7 @@ #include "active_tile_data.h" #include "calendar.h" +#include "catalua_type_operators.h" #include "color.h" #include "numeric_interval.h" #include "poly_serialized.h" @@ -481,6 +482,8 @@ struct ter_t : map_data_common_t { void load( const JsonObject &jo, const std::string &src ) override; void check() const override; static const std::vector &get_all(); + + LUA_TYPE_OPS( ter_t, id ); }; void set_ter_ids(); @@ -534,6 +537,8 @@ struct furn_t : map_data_common_t { void load( const JsonObject &jo, const std::string &src ) override; void check() const override; static const std::vector &get_all(); + + LUA_TYPE_OPS( furn_t, id ); }; void load_furniture( const JsonObject &jo, const std::string &src ); diff --git a/src/mapgen.cpp b/src/mapgen.cpp index a690c5703614..5aee6d827cbe 100644 --- a/src/mapgen.cpp +++ b/src/mapgen.cpp @@ -17,6 +17,7 @@ #include "basecamp.h" #include "calendar.h" #include "catacharset.h" +#include "catalua.h" #include "character_id.h" #include "clzones.h" #include "numeric_interval.h" @@ -192,6 +193,13 @@ void map::generate( const tripoint &p, const time_point &when ) } } + cata::run_on_mapgen_postprocess_hooks( + *DynamicDataLoader::get_instance().lua, + *this, + sm_to_omt_copy( p ), + when + ); + // Okay, we know who are neighbors are. Let's draw! // And finally save used submaps and delete the rest. for( int i = 0; i < my_MAPSIZE; i++ ) { diff --git a/src/mattack_actors.cpp b/src/mattack_actors.cpp index c97b2b55a1c2..14b27600087f 100644 --- a/src/mattack_actors.cpp +++ b/src/mattack_actors.cpp @@ -581,6 +581,10 @@ bool gun_actor::call( monster &z ) const } } + // One last check to make sure we're not firing on a friendly + if( z.attitude_to( *target ) == Creature::A_FRIENDLY ) { + return false; + } int dist = rl_dist( z.pos(), aim_at ); for( const auto &e : ranges ) { if( dist >= e.first.first && dist <= e.first.second ) { diff --git a/src/mod_manager.cpp b/src/mod_manager.cpp index 726783b51f6f..fa7876971a8b 100644 --- a/src/mod_manager.cpp +++ b/src/mod_manager.cpp @@ -280,6 +280,7 @@ std::optional load_modfile( const JsonObject &jo, const std::st assign( jo, "authors", modfile.authors ); assign( jo, "maintainers", modfile.maintainers ); assign( jo, "version", modfile.version ); + assign( jo, "lua_api_version", modfile.lua_api_version ); assign( jo, "dependencies", modfile.dependencies ); assign( jo, "conflicts", modfile.conflicts ); assign( jo, "core", modfile.core ); diff --git a/src/mod_manager.h b/src/mod_manager.h index 2d32c608a23c..54a4e6cfab2a 100644 --- a/src/mod_manager.h +++ b/src/mod_manager.h @@ -4,6 +4,7 @@ #include #include +#include #include #include #include @@ -76,6 +77,9 @@ struct MOD_INFORMATION { */ std::string version; + /** If mod uses Lua API, specifies version of the API being used. */ + std::optional lua_api_version; + /** What other mods must be loaded prior to this one? */ std::vector dependencies; diff --git a/src/mod_manager_ui.cpp b/src/mod_manager_ui.cpp index c834001190d9..ff4a94d6c523 100644 --- a/src/mod_manager_ui.cpp +++ b/src/mod_manager_ui.cpp @@ -5,6 +5,7 @@ #include "color.h" #include "debug.h" +#include "catalua.h" #include "dependency_tree.h" #include "output.h" #include "string_formatter.h" @@ -76,6 +77,17 @@ std::string mod_ui::get_information( const MOD_INFORMATION *mod ) info += colorize( _( "Mod version" ), c_light_blue ) + ": " + mod->version + "\n"; } + if( mod->lua_api_version ) { + nc_color col_lua = cata::has_lua() ? c_light_blue : c_red; + int this_api = cata::get_lua_api_version(); + nc_color col_api = this_api == *mod->lua_api_version ? c_white : c_yellow; + info += string_format( + _( "%s: API version %s\n" ), + colorize( _( "Needs Lua" ), col_lua ), + colorize( string_format( "%d", *mod->lua_api_version ), col_api ) + ); + } + if( !mod->description().empty() ) { info += mod->description() + "\n"; } diff --git a/src/monmove.cpp b/src/monmove.cpp index d11bb56ea23d..0317a69d93ca 100644 --- a/src/monmove.cpp +++ b/src/monmove.cpp @@ -937,6 +937,11 @@ void monster::move() // in both circular and roguelike distance modes. const float distance_to_target = trig_dist( pos(), destination ); for( tripoint &candidate : squares_closer_to( pos(), destination ) ) { + // rare scenario when monster is on the border of the map and it's goal is outside of the map + if( !here.inbounds( candidate ) ) { + continue; + } + bool via_ramp = false; if( here.has_flag( TFLAG_RAMP_UP, candidate ) ) { via_ramp = true; diff --git a/src/monster.cpp b/src/monster.cpp index e0905a14c720..33324f6cc970 100644 --- a/src/monster.cpp +++ b/src/monster.cpp @@ -1250,12 +1250,19 @@ Creature::Attitude monster::attitude_to( const Creature &other ) const return A_FRIENDLY; } + static const string_id faction_zombie( "zombie" ); auto faction_att = faction.obj().attitude( m->faction ); if( ( friendly != 0 && m->friendly != 0 ) || ( friendly == 0 && m->friendly == 0 && faction_att == MFA_FRIENDLY ) ) { // Friendly (to player) monsters are friendly to each other // Unfriendly monsters go by faction attitude return A_FRIENDLY; + } else if( g->u.has_trait( trait_PROF_FERAL ) && ( faction == faction_zombie || + type->in_species( ZOMBIE ) ) && ( m->faction == faction_zombie || + m->type->in_species( ZOMBIE ) ) ) { + // Zombies ignoring a feral survivor aren't quite the same as friendly + // Ignore actually-friendly zombies/ferals but not other friendlies like reprogramed bots + return A_FRIENDLY; } else if( ( friendly == 0 && m->friendly == 0 && faction_att == MFA_HATE ) ) { // Stuff that hates a specific faction will always attack that faction return A_HOSTILE; @@ -1350,12 +1357,11 @@ monster_attitude monster::attitude( const Character *u ) const if( has_flag( MF_ANIMAL ) ) { if( u->has_trait( trait_PROF_FERAL ) ) { - // We want wildlife to amp their normal fight-or-flight response up to eleven, so anger_relation won't cut it. + // We want all wildlife to amp their fight-or-flight response up to eleven, so anger adjustments in general won't cut it. if( effective_anger >= -10 ) { - effective_anger += 25; - } - if( effective_anger < -10 ) { - effective_morale -= 100; + return MATT_ATTACK; + } else { + return MATT_FLEE; } } else if( u->has_trait( trait_ANIMALEMPATH ) ) { effective_anger -= 10; @@ -3156,7 +3162,7 @@ void monster::hear_sound( const tripoint &source, const int vol, const int dist } static const string_id faction_zombie( "zombie" ); - const bool feral_friend = ( faction == faction_zombie || !type->in_species( ZOMBIE ) ) && + const bool feral_friend = ( faction == faction_zombie || type->in_species( ZOMBIE ) ) && g->u.has_trait( trait_PROF_FERAL ) && !g->u.has_effect( effect_feral_infighting_punishment ); // Hackery: If player is currently a feral and you're a zombie, ignore any sounds close to their position. diff --git a/src/npc.cpp b/src/npc.cpp index ceec2ee4ebff..7d426da8916a 100644 --- a/src/npc.cpp +++ b/src/npc.cpp @@ -3016,11 +3016,8 @@ std::set npc::get_path_avoid() const mfaction_id npc::get_monster_faction() const { - if( my_fac ) { - string_id my_mon_fac = string_id( my_fac->mon_faction ); - if( my_mon_fac.is_valid() ) { - return my_mon_fac; - } + if( my_fac && my_fac->mon_faction.is_valid() ) { + return my_fac->mon_faction; } // legacy checks diff --git a/src/npcmove.cpp b/src/npcmove.cpp index c1f0033bfb7c..f62f22c68aa4 100644 --- a/src/npcmove.cpp +++ b/src/npcmove.cpp @@ -422,20 +422,20 @@ void npc::assess_danger() cur_threat_map[ threat_dir ] = 0.25f * ai_cache.threat_map[ threat_dir ]; } map &here = get_map(); + // cache string_id -> int_id conversion before hot loop + const field_type_id fd_fire = ::fd_fire; // first, check if we're about to be consumed by fire - // TODO: Use the field cache + // `map::get_field` uses `field_cache`, so in general case (no fire) it provides an early exit for( const tripoint &pt : here.points_in_radius( pos(), 6 ) ) { - if( pt == pos() || here.has_flag( TFLAG_FIRE_CONTAINER, pt ) ) { + if( pt == pos() || !here.get_field( pt, fd_fire ) || here.has_flag( TFLAG_FIRE_CONTAINER, pt ) ) { continue; } - if( here.get_field( pt, fd_fire ) != nullptr ) { - int dist = rl_dist( pos(), pt ); - cur_threat_map[direction_from( pos(), pt )] += 2.0f * ( NPC_DANGER_MAX - dist ); - if( dist < 3 && !has_effect( effect_npc_fire_bad ) ) { - warn_about( "fire_bad", 1_minutes ); - add_effect( effect_npc_fire_bad, 5_turns ); - path.clear(); - } + const int dist = rl_dist( pos(), pt ); + cur_threat_map[direction_from( pos(), pt )] += 2.0f * ( NPC_DANGER_MAX - dist ); + if( dist < 3 && !has_effect( effect_npc_fire_bad ) ) { + warn_about( "fire_bad", 1_minutes ); + add_effect( effect_npc_fire_bad, 5_turns ); + path.clear(); } } diff --git a/src/options.cpp b/src/options.cpp index 64ad7c5cd109..ab5d4d49168e 100644 --- a/src/options.cpp +++ b/src/options.cpp @@ -135,6 +135,11 @@ static const std::vector debug_log_classes = { { translate_marker( "Messages related to SDL, tiles, tilesets and sound." ), false }, + { + DC::Lua, "DEBUGLOG_CL_LUA", translate_marker( "Lua" ), + translate_marker( "Messages from Lua scripts." ), + true + }, } }; @@ -1827,6 +1832,11 @@ void options_manager::add_options_graphics() get_option( "ANIMATION_DELAY" ).setPrerequisite( "ANIMATIONS" ); + add( "BULLETS_AS_LASERS", graphics, translate_marker( "Draw bullets as lines" ), + translate_marker( "If true, bullets are drawn as lines of images, and the animation lasts only one frame." ), + false + ); + add( "BLINK_SPEED", graphics, translate_marker( "Blinking effects speed" ), translate_marker( "The speed of every blinking effects in ms." ), 100, 5000, 800 diff --git a/src/overmap.cpp b/src/overmap.cpp index 6f09daa83cf3..f311360e03bb 100644 --- a/src/overmap.cpp +++ b/src/overmap.cpp @@ -1146,7 +1146,7 @@ overmap::overmap( const point_abs_om &p ) : loc( p ) // gonna die now =[ debugmsg( "overmap %s: can't find region '%s'", loc.to_string(), rsettings_id.c_str() ); } - settings = pimpl( rsit->second ); + settings = &rsit->second; init_layers(); } @@ -1166,7 +1166,7 @@ void overmap::populate( overmap_special_batch &enabled_specials ) void overmap::populate() { overmap_special_batch enabled_specials = overmap_specials::get_default_batch( loc ); - overmap_feature_flag_settings &overmap_feature_flag = settings->overmap_feature_flag; + const overmap_feature_flag_settings &overmap_feature_flag = settings->overmap_feature_flag; const bool should_blacklist = !overmap_feature_flag.blacklist.empty(); const bool should_whitelist = !overmap_feature_flag.whitelist.empty(); diff --git a/src/overmap.h b/src/overmap.h index c090af42bcad..9e6dc3a513c7 100644 --- a/src/overmap.h +++ b/src/overmap.h @@ -349,7 +349,7 @@ class overmap // TODO: Should have individual instances grouped by placement (ie. 2 adjacent houses aren't one house) std::unordered_map overmap_special_placements; - pimpl settings; + const regional_settings *settings; oter_id get_default_terrain( int z ) const; diff --git a/src/path_info.cpp b/src/path_info.cpp index a1e7aac6d2ed..88bbeea7e562 100644 --- a/src/path_info.cpp +++ b/src/path_info.cpp @@ -303,6 +303,10 @@ std::string PATH_INFO::soundpack_conf() { return "soundpack.txt"; } +std::string PATH_INFO::lua_doc_output() +{ + return config_dir_value + "lua_doc.md"; +} std::string PATH_INFO::gfxdir() { return gfxdir_value; diff --git a/src/path_info.h b/src/path_info.h index 10d6e6ccea0d..65b7c467488f 100644 --- a/src/path_info.h +++ b/src/path_info.h @@ -57,6 +57,7 @@ std::string mods_replacements(); std::string mods_dev_default(); std::string mods_user_default(); std::string soundpack_conf(); +std::string lua_doc_output(); std::string credits(); std::string motd(); diff --git a/src/runtime_handlers.cpp b/src/runtime_handlers.cpp index d99e9bd79b49..9b4f01f562e6 100644 --- a/src/runtime_handlers.cpp +++ b/src/runtime_handlers.cpp @@ -1,11 +1,13 @@ #include "runtime_handlers.h" #include "cursesdef.h" #include "debug.h" +#include "init.h" #include "game.h" [[ noreturn ]] void exit_handler( int status ) { + DynamicDataLoader::get_instance().unload_data(); deinitDebug(); g.reset(); catacurses::endwin(); diff --git a/src/savegame.cpp b/src/savegame.cpp index a38bf911fc76..8e086d144949 100644 --- a/src/savegame.cpp +++ b/src/savegame.cpp @@ -493,7 +493,7 @@ void overmap::unserialize( std::istream &fin, const std::string &file_path ) t_regional_settings_map_citr rit = region_settings_map.find( new_region_id ); if( rit != region_settings_map.end() ) { // TODO: optimize - settings = pimpl( rit->second ); + settings = &rit->second; } } } else if( name == "mongroups" ) { diff --git a/src/sdlsound.cpp b/src/sdlsound.cpp index 790164948aad..3e6497fe69cd 100644 --- a/src/sdlsound.cpp +++ b/src/sdlsound.cpp @@ -683,10 +683,24 @@ void load_soundset() // Preload sound effects for( const id_and_variant &preload : sfx_preload ) { - const auto find_result = sfx_resources.sound_effects.find( preload ); - if( find_result != sfx_resources.sound_effects.end() ) { - for( const auto &sfx : find_result->second ) { - get_sfx_resource( sfx.resource_id ); + const auto& [id, variant] = preload; + + // HACK + // context: @link https://discord.com/channels/830879262763909202/830916451517857894/1140806895200911493 + if( variant == "all" ) { + for( const auto &[key, sfxs] : sfx_resources.sound_effects ) { + if( key.first == id ) { + for( const auto &sfx : sfxs ) { + get_sfx_resource( sfx.resource_id ); + } + } + } + } else { + const auto find_result = sfx_resources.sound_effects.find( preload ); + if( find_result != sfx_resources.sound_effects.end() ) { + for( const auto &sfx : find_result->second ) { + get_sfx_resource( sfx.resource_id ); + } } } } diff --git a/src/sdltiles.cpp b/src/sdltiles.cpp index c38963910cb7..cb2d23198a69 100644 --- a/src/sdltiles.cpp +++ b/src/sdltiles.cpp @@ -3520,6 +3520,7 @@ void catacurses::init_interface() get_options().init(); get_options().load(); + get_options().save(); font_loader fl; fl.load(); diff --git a/src/sol/changes.txt b/src/sol/changes.txt new file mode 100644 index 000000000000..e8cd4b1a8e13 --- /dev/null +++ b/src/sol/changes.txt @@ -0,0 +1,7 @@ +Changes done to sol.hpp header: + +Added include guard to prevent inclusions outside catalua_sol.h + +#ifndef CATALUA_SOL_WRAPPED +static_assert(false, "sol.hpp must be included via catalua_sol.h"); +#endif diff --git a/src/sol/config.hpp b/src/sol/config.hpp new file mode 100644 index 000000000000..823a0e939527 --- /dev/null +++ b/src/sol/config.hpp @@ -0,0 +1,67 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2022-06-25 08:14:19.336233 UTC +// This header was generated with sol v3.3.0 (revision eba86625) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_CONFIG_HPP +#define SOL_SINGLE_CONFIG_HPP + +// beginning of sol/config.hpp + +/* Base, empty configuration file! + + To override, place a file in your include paths of the form: + +. (your include path here) +| sol (directory, or equivalent) + | config.hpp (your config.hpp file) + + So that when sol2 includes the file + +#include + + it gives you the configuration values you desire. Configuration values can be +seen in the safety.rst of the doc/src, or at +https://sol2.readthedocs.io/en/latest/safety.html ! You can also pass them through +the build system, or the command line options of your compiler. + +*/ + +// end of sol/config.hpp + +// We compile Lua parts with C++ compiler, so sol doesn't need to use extern "C" +#define SOL_BUILD_CXX_MODE 1 + +// Be helpful and verbose, even at the cost of speed +#define SOL_ALL_SAFETIES_ON 1 + +// According to a comment in Sol2, nil is an Objective C/C++ Keyword that's found in OSX SDK. +// We're not using Objective C/C++, so we should be okay. +// Still, Sol2 disables it by default on OSX, so here we forcefully re-enable it back. +#if defined(nil) + static_assert(false, "Sol's nil conflicts with existing nil define in some C++ include!") +#endif +#define SOL_NO_NIL 0 + +#endif // SOL_SINGLE_CONFIG_HPP diff --git a/src/sol/forward.hpp b/src/sol/forward.hpp new file mode 100644 index 000000000000..8690690871f6 --- /dev/null +++ b/src/sol/forward.hpp @@ -0,0 +1,1321 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2022-06-25 08:14:19.328625 UTC +// This header was generated with sol v3.3.0 (revision eba86625) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_FORWARD_HPP +#define SOL_SINGLE_INCLUDE_FORWARD_HPP + +// beginning of sol/forward.hpp + +#ifndef SOL_FORWARD_HPP +#define SOL_FORWARD_HPP + +// beginning of sol/version.hpp + +#include + +#define SOL_VERSION_MAJOR 3 +#define SOL_VERSION_MINOR 2 +#define SOL_VERSION_PATCH 3 +#define SOL_VERSION_STRING "3.2.3" +#define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH)) + +#define SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN +#define SOL_TOKEN_TO_STRING_I_(_TOKEN) SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) + +#define SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT +#define SOL_CONCAT_TOKENS_I_(_LEFT, _RIGHT) SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) + +#define SOL_RAW_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) +#define SOL_RAW_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) +#define SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) +#define SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) + +#define SOL_IS_ON(OP_SYMBOL) SOL_RAW_IS_ON(OP_SYMBOL ## _I_) +#define SOL_IS_OFF(OP_SYMBOL) SOL_RAW_IS_OFF(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_ON(OP_SYMBOL) SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_OFF(OP_SYMBOL) SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL ## _I_) + +#define SOL_ON | +#define SOL_OFF ^ +#define SOL_DEFAULT_ON + +#define SOL_DEFAULT_OFF - + +#if defined(SOL_BUILD_CXX_MODE) + #if (SOL_BUILD_CXX_MODE != 0) + #define SOL_BUILD_CXX_MODE_I_ SOL_ON + #else + #define SOL_BUILD_CXX_MODE_I_ SOL_OFF + #endif +#elif defined(__cplusplus) + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_BUILD_C_MODE) + #if (SOL_BUILD_C_MODE != 0) + #define SOL_BUILD_C_MODE_I_ SOL_ON + #else + #define SOL_BUILD_C_MODE_I_ SOL_OFF + #endif +#elif defined(__STDC__) + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if SOL_IS_ON(SOL_BUILD_C_MODE) + #include + #include + #include +#else + #include + #include + #include +#endif + +#if defined(SOL_COMPILER_VCXX) + #if defined(SOL_COMPILER_VCXX != 0) + #define SOL_COMPILER_VCXX_I_ SOL_ON + #else + #define SOL_COMPILER_VCXX_I_ SOL_OFF + #endif +#elif defined(_MSC_VER) + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_GCC) + #if defined(SOL_COMPILER_GCC != 0) + #define SOL_COMPILER_GCC_I_ SOL_ON + #else + #define SOL_COMPILER_GCC_I_ SOL_OFF + #endif +#elif defined(__GNUC__) + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_CLANG) + #if defined(SOL_COMPILER_CLANG != 0) + #define SOL_COMPILER_CLANG_I_ SOL_ON + #else + #define SOL_COMPILER_CLANG_I_ SOL_OFF + #endif +#elif defined(__clang__) + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_EDG) + #if defined(SOL_COMPILER_EDG != 0) + #define SOL_COMPILER_EDG_I_ SOL_ON + #else + #define SOL_COMPILER_EDG_I_ SOL_OFF + #endif +#else + #define SOL_COMPILER_EDG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_MINGW) + #if (SOL_COMPILER_MINGW != 0) + #define SOL_COMPILER_MINGW_I_ SOL_ON + #else + #define SOL_COMPILER_MINGW_I_ SOL_OFF + #endif +#elif defined(__MINGW32__) + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_OFF +#endif + +#if SIZE_MAX <= 0xFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_ON + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_OFF +#elif SIZE_MAX <= 0xFFFFFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_ON + #define SOL_PLATFORM_X64_I_ SOL_OFF +#else + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_ON +#endif + +#define SOL_PLATFORM_ARM32_I_ SOL_OFF +#define SOL_PLATFORM_ARM64_I_ SOL_OFF + +#if defined(SOL_PLATFORM_WINDOWS) + #if (SOL_PLATFORM_WINDOWS != 0) + #define SOL_PLATFORM_WINDOWS_I_ SOL_ON + #else + #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF + #endif +#elif defined(_WIN32) + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_CYGWIN) + #if (SOL_PLATFORM_CYGWIN != 0) + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #else + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #endif +#elif defined(__CYGWIN__) + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_APPLE) + #if (SOL_PLATFORM_APPLE != 0) + #define SOL_PLATFORM_APPLE_I_ SOL_ON + #else + #define SOL_PLATFORM_APPLE_I_ SOL_OFF + #endif +#elif defined(__APPLE__) + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_UNIX) + #if (SOL_PLATFORM_UNIX != 0) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF + #endif +#elif defined(__unix__) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_LINUX) + #if (SOL_PLATFORM_LINUX != 0) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF + #endif +#elif defined(__LINUX__) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF +#define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF + +#if defined(SOL_IN_DEBUG_DETECTED) + #if SOL_IN_DEBUG_DETECTED != 0 + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#elif !defined(NDEBUG) + #if SOL_IS_ON(SOL_COMPILER_VCXX) && defined(_DEBUG) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #elif (SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC)) && !defined(__OPTIMIZE__) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF +#endif // We are in a debug mode of some sort + +#if defined(SOL_NO_EXCEPTIONS) + #if (SOL_NO_EXCEPTIONS != 0) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPUNWIND) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__EXCEPTIONS) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#else + #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_RTTI) + #if (SOL_NO_RTTI != 0) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPRTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__GXX_RTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#else + #define SOL_RTTI_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_THREAD_LOCAL) + #if SOL_NO_THREAD_LOCAL != 0 + #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF + #else + #define SOL_USE_THREAD_LOCAL_I_ SOL_ON + #endif +#else + #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON +#endif // thread_local keyword is bjorked on some platforms + +#if defined(SOL_ALL_SAFETIES_ON) + #if SOL_ALL_SAFETIES_ON != 0 + #define SOL_ALL_SAFETIES_ON_I_ SOL_ON + #else + #define SOL_ALL_SAFETIES_ON_I_ SOL_OFF + #endif +#else + #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_GETTER) + #if SOL_SAFE_GETTER != 0 + #define SOL_SAFE_GETTER_I_ SOL_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_GETTER_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_USERTYPE) + #if SOL_SAFE_USERTYPE != 0 + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_REFERENCES) + #if SOL_SAFE_REFERENCES != 0 + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTIONS) + #if SOL_SAFE_FUNCTIONS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#elif defined (SOL_SAFE_FUNCTION_OBJECTS) + #if SOL_SAFE_FUNCTION_OBJECTS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTION_CALLS) + #if SOL_SAFE_FUNCTION_CALLS != 0 + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_PROXIES) + #if SOL_SAFE_PROXIES != 0 + #define SOL_SAFE_PROXIES_I_ SOL_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_NUMERICS) + #if SOL_SAFE_NUMERICS != 0 + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_ALL_INTEGER_VALUES_FIT) + #if (SOL_ALL_INTEGER_VALUES_FIT != 0) + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON + #else + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF + #endif +#elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_SAFE_NUMERICS) + // if numerics is intentionally turned off, flip this on + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON +#else + // default to off + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_STACK_CHECK) + #if SOL_SAFE_STACK_CHECK != 0 + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_CHECK_NUMBER_PRECISION) + #if SOL_NO_CHECK_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#elif defined(SOL_NO_CHECKING_NUMBER_PRECISION) + #if SOL_NO_CHECKING_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_SAFE_NUMERICS) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_STRINGS_ARE_NUMBERS) + #if (SOL_STRINGS_ARE_NUMBERS != 0) + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON + #else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF + #endif +#else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ENABLE_INTEROP) + #if SOL_ENABLE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#elif defined(SOL_USE_INTEROP) + #if SOL_USE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#else + #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_NIL) + #if (SOL_NO_NIL != 0) + #define SOL_NIL_I_ SOL_OFF + #else + #define SOL_NIL_I_ SOL_ON + #endif +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) + #define SOL_NIL_I_ SOL_DEFAULT_OFF +#else + #define SOL_NIL_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USERTYPE_TYPE_BINDING_INFO) + #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0) + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON + #else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF + #endif +#else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON +#endif // We should generate a my_type.__type table with lots of class information for usertypes + +#if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT) + #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES) + #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON +#endif // make is_automagical on/off by default + +#if defined(SOL_STD_VARIANT) + #if (SOL_STD_VARIANT != 0) + #define SOL_STD_VARIANT_I_ SOL_ON + #else + #define SOL_STD_VARIANT_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_COMPILER_CLANG) && SOL_IS_ON(SOL_PLATFORM_APPLE) + #if defined(__has_include) + #if __has_include() + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #endif +#endif // make is_automagical on/off by default + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) + #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #endif +#else + #if defined(__cpp_noexcept_function_type) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L)) + // There is a bug in the VC++ compiler?? + // on /std:c++latest under x86 conditions (VS 15.5.2), + // compiler errors are tossed for noexcept markings being on function types + // that are identical in every other way to their non-noexcept marked types function types... + // VS 2019: There is absolutely a bug. + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON + #endif +#endif // noexcept is part of a function's type + +#if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && SOL_STACK_STRING_OPTIMIZATION_SIZE > 0 + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE +#else + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024 +#endif + +#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_ID_SIZE_I_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_I_ 512 +#endif + +#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 + #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_I_ 2048 +#endif + +#if defined(SOL_PRINT_ERRORS) + #if (SOL_PRINT_ERRORS != 0) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#endif + +#if defined(SOL_DEFAULT_PASS_ON_ERROR) + #if (SOL_DEFAULT_PASS_ON_ERROR != 0) + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON + #else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUA) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUA) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUA_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUAJIT) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUAJIT) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUAJIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_LUA_HPP) + #if (SOL_NO_LUA_HPP != 0) + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #else + #define SOL_USE_LUA_HPP_I_ SOL_ON + #endif +#elif defined(SOL_USING_CXX_LUA) + #define SOL_USE_LUA_HPP_I_ SOL_OFF +#elif defined(__has_include) + #if __has_include() + #define SOL_USE_LUA_HPP_I_ SOL_ON + #else + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #endif +#else + #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_CONTAINERS_START) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START +#elif defined(SOL_CONTAINERS_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX +#elif defined(SOL_CONTAINER_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX +#else + #define SOL_CONTAINER_START_INDEX_I_ 1 +#endif + +#if defined (SOL_NO_MEMORY_ALIGNMENT) + #if (SOL_NO_MEMORY_ALIGNMENT != 0) + #define SOL_ALIGN_MEMORY_I_ SOL_OFF + #else + #define SOL_ALIGN_MEMORY_I_ SOL_ON + #endif +#else + #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USE_BOOST) + #if (SOL_USE_BOOST != 0) + #define SOL_USE_BOOST_I_ SOL_ON + #else + #define SOL_USE_BOOST_I_ SOL_OFF + #endif +#else + #define SOL_USE_BOOST_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USE_UNSAFE_BASE_LOOKUP) + #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0) + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON + #else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF + #endif +#else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_INSIDE_UNREAL) + #if (SOL_INSIDE_UNREAL != 0) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF + #endif +#else + #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_COMPAT) + #if (SOL_NO_COMPAT != 0) + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF + #else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON + #endif +#else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE) + #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0) + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON + #else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF + #endif +#else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + #if (SOL_FUNCTION_CALL_VALUE_SEMANTICS != 0) + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_ON + #else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_OFF + #endif +#else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_MINGW_CCTYPE_IS_POISONED) + #if (SOL_MINGW_CCTYPE_IS_POISONED != 0) + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON + #else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_MINGW) && defined(__GNUC__) && (__GNUC__ < 6) + // MinGW is off its rocker in some places... + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_ON +#else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CHAR8_T) + #if (SOL_CHAR8_T != 0) + #define SOL_CHAR8_T_I_ SOL_ON + #else + #define SOL_CHAR8_T_I_ SOL_OFF + #endif +#else + #if defined(__cpp_char8_t) + #define SOL_CHAR8_T_I_ SOL_DEFAULT_ON + #else + #define SOL_CHAR8_T_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if SOL_IS_ON(SOL_USE_BOOST) + #include + + #if BOOST_VERSION >= 107500 // Since Boost 1.75.0 boost::none is constexpr + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr + #else + #define SOL_BOOST_NONE_CONSTEXPR_I_ const + #endif // BOOST_VERSION +#else + // assume boost isn't using a garbage version + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr +#endif + +#if defined(SOL2_CI) + #if (SOL2_CI != 0) + #define SOL2_CI_I_ SOL_ON + #else + #define SOL2_CI_I_ SOL_OFF + #endif +#else + #define SOL2_CI_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_C_ASSERT) + #define SOL_USER_C_ASSERT_I_ SOL_ON +#else + #define SOL_USER_C_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_M_ASSERT) + #define SOL_USER_M_ASSERT_I_ SOL_ON +#else + #define SOL_USER_M_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +// beginning of sol/prologue.hpp + +#if defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue." +#endif + +#define SOL_PROLOGUE_I_ 1 + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define _FWD(...) static_cast( __VA_ARGS__ ) + + #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) + #else + #include + + #define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) + #endif +#endif + +// end of sol/prologue.hpp + +// beginning of sol/epilogue.hpp + +#if !defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue is missing from this translation unit." +#else + #undef SOL_PROLOGUE_I_ +#endif + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #undef _FWD + #undef _MOVE +#endif + +// end of sol/epilogue.hpp + +// beginning of sol/detail/build_version.hpp + +#if defined(SOL_DLL) + #if (SOL_DLL != 0) + #define SOL_DLL_I_ SOL_ON + #else + #define SOL_DLL_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL)) + #define SOL_DLL_I_ SOL_DEFAULT_ON +#else + #define SOL_DLL_I_ SOL_DEFAULT_OFF +#endif // DLL definition + +#if defined(SOL_HEADER_ONLY) + #if (SOL_HEADER_ONLY != 0) + #define SOL_HEADER_ONLY_I_ SOL_ON + #else + #define SOL_HEADER_ONLY_I_ SOL_OFF + #endif +#else + #define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_BUILD) + #if (SOL_BUILD != 0) + #define SOL_BUILD_I_ SOL_ON + #else + #define SOL_BUILD_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_BUILD_I_ SOL_DEFAULT_OFF +#else + #define SOL_BUILD_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_UNITY_BUILD) + #if (SOL_UNITY_BUILD != 0) + #define SOL_UNITY_BUILD_I_ SOL_ON + #else + #define SOL_UNITY_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_C_FUNCTION_LINKAGE) + #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE +#else + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + // C++ + #define SOL_C_FUNCTION_LINKAGE_I_ extern "C" + #else + // normal + #define SOL_C_FUNCTION_LINKAGE_I_ + #endif // C++ or not +#endif // Linkage specification for C functions + +#if defined(SOL_API_LINKAGE) + #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE +#else + #if SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN) + // MSVC Compiler; or, Windows, or Cygwin platforms + #if SOL_IS_ON(SOL_BUILD) + // Building the library + #if SOL_IS_ON(SOL_COMPILER_GCC) + // Using GCC + #define SOL_API_LINKAGE_I_ __attribute__((dllexport)) + #else + // Using Clang, MSVC, etc... + #define SOL_API_LINKAGE_I_ __declspec(dllexport) + #endif + #else + #if SOL_IS_ON(SOL_COMPILER_GCC) + #define SOL_API_LINKAGE_I_ __attribute__((dllimport)) + #else + #define SOL_API_LINKAGE_I_ __declspec(dllimport) + #endif + #endif + #else + // extern if building normally on non-MSVC + #define SOL_API_LINKAGE_I_ extern + #endif + #elif SOL_IS_ON(SOL_UNITY_BUILD) + // Built-in library, like how stb typical works + #if SOL_IS_ON(SOL_HEADER_ONLY) + // Header only, so functions are defined "inline" + #define SOL_API_LINKAGE_I_ inline + #else + // Not header only, so seperately compiled files + #define SOL_API_LINKAGE_I_ extern + #endif + #else + // Normal static library + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define SOL_API_LINKAGE_I_ + #else + #define SOL_API_LINKAGE_I_ extern + #endif + #endif // DLL or not +#endif // Build definitions + +#if defined(SOL_PUBLIC_FUNC_DECL) + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL +#else + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DECL_) + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_ +#else + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_PUBLIC_FUNC_DEF) + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF +#else + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DEF) + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF +#else + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_FUNC_DECL) + #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_FUNC_DEFN) + #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DEFN_I_ __declspec(dllexport) + #else + #define SOL_FUNC_DEFN_I_ __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DEFN_I_ + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DECL) + #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DEFN) + #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DEFN_I_ + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif +#endif + +// end of sol/detail/build_version.hpp + +// end of sol/version.hpp + +#include +#include +#include + +#if SOL_IS_ON(SOL_USE_CXX_LUA) || SOL_IS_ON(SOL_USE_CXX_LUAJIT) +struct lua_State; +#else +extern "C" { +struct lua_State; +} +#endif // C++ Mangling for Lua vs. Not + +namespace sol { + + enum class type; + + class stateless_reference; + template + class basic_reference; + using reference = basic_reference; + using main_reference = basic_reference; + class stateless_stack_reference; + class stack_reference; + + template + class basic_bytecode; + + struct lua_value; + + struct proxy_base_tag; + template + struct proxy_base; + template + struct table_proxy; + + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using main_table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = basic_table_core; + using table = table_core; + using global_table = table_core; + using main_table = main_table_core; + using main_global_table = main_table_core; + using stack_table = stack_table_core; + using stack_global_table = stack_table_core; + + template + struct basic_lua_table; + using lua_table = basic_lua_table; + using stack_lua_table = basic_lua_table; + + template + class basic_usertype; + template + using usertype = basic_usertype; + template + using stack_usertype = basic_usertype; + + template + class basic_metatable; + using metatable = basic_metatable; + using stack_metatable = basic_metatable; + + template + struct basic_environment; + using environment = basic_environment; + using main_environment = basic_environment; + using stack_environment = basic_environment; + + template + class basic_function; + template + class basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using main_unsafe_function = basic_function; + using main_safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; + using stack_aligned_unsafe_function = basic_function; + using stack_aligned_safe_function = basic_protected_function; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; + using stack_aligned_function = stack_aligned_safe_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; + using stack_aligned_function = stack_aligned_unsafe_function; +#endif + using stack_aligned_stack_handler_function = basic_protected_function; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template + class basic_object_base; + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + template + class basic_coroutine; + template + class basic_packaged_coroutine; + template + class basic_thread; + + using object = basic_object; + using userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using thread = basic_thread; + using coroutine = basic_coroutine; + using packaged_coroutine = basic_packaged_coroutine; + using main_object = basic_object; + using main_userdata = basic_userdata; + using main_lightuserdata = basic_lightuserdata; + using main_coroutine = basic_coroutine; + using stack_object = basic_object; + using stack_userdata = basic_userdata; + using stack_lightuserdata = basic_lightuserdata; + using stack_thread = basic_thread; + using stack_coroutine = basic_coroutine; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + class state_view; + class state; + + template + struct as_table_t; + template + struct as_container_t; + template + struct nested; + template + struct light; + template + struct user; + template + struct as_args_t; + template + struct protect_t; + template + struct policy_wrapper; + + template + struct usertype_traits; + template + struct unique_usertype_traits; + + template + struct types { + typedef std::make_index_sequence indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + + template + struct derive : std::false_type { + typedef types<> type; + }; + + template + struct base : std::false_type { + typedef types<> type; + }; + + template + struct weak_derive { + static bool value; + }; + + template + bool weak_derive::value = false; + + namespace stack { + struct record; + } + +#if SOL_IS_OFF(SOL_USE_BOOST) + template + class optional; + + template + class optional; +#endif + + using check_handler_type = int(lua_State*, int, type, type, const char*); + +} // namespace sol + +#define SOL_BASE_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct base : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() +#define SOL_DERIVED_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct derive : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() + +#endif // SOL_FORWARD_HPP +// end of sol/forward.hpp + +#endif // SOL_SINGLE_INCLUDE_FORWARD_HPP diff --git a/src/sol/sol.hpp b/src/sol/sol.hpp new file mode 100644 index 000000000000..befd64414439 --- /dev/null +++ b/src/sol/sol.hpp @@ -0,0 +1,28911 @@ +// The MIT License (MIT) + +// Copyright (c) 2013-2020 Rapptz, ThePhD and contributors + +// Permission is hereby granted, free of charge, to any person obtaining a copy of +// this software and associated documentation files (the "Software"), to deal in +// the Software without restriction, including without limitation the rights to +// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of +// the Software, and to permit persons to whom the Software is furnished to do so, +// subject to the following conditions: + +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. + +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS +// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR +// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER +// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN +// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + +// This file was generated with a script. +// Generated 2022-06-25 08:14:19.151876 UTC +// This header was generated with sol v3.3.0 (revision eba86625) +// https://github.com/ThePhD/sol2 + +#ifndef SOL_SINGLE_INCLUDE_HPP +#define SOL_SINGLE_INCLUDE_HPP + +#ifndef CATALUA_SOL_WRAPPED +static_assert(false, "sol.hpp must be included via catalua_sol.h"); +#endif + +// beginning of sol/sol.hpp + +#ifndef SOL_HPP +#define SOL_HPP + +// beginning of sol/version.hpp + +#include + +#define SOL_VERSION_MAJOR 3 +#define SOL_VERSION_MINOR 2 +#define SOL_VERSION_PATCH 3 +#define SOL_VERSION_STRING "3.2.3" +#define SOL_VERSION ((SOL_VERSION_MAJOR * 100000) + (SOL_VERSION_MINOR * 100) + (SOL_VERSION_PATCH)) + +#define SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) #_TOKEN +#define SOL_TOKEN_TO_STRING_I_(_TOKEN) SOL_TOKEN_TO_STRING_POST_EXPANSION_I_(_TOKEN) + +#define SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) _LEFT##_RIGHT +#define SOL_CONCAT_TOKENS_I_(_LEFT, _RIGHT) SOL_CONCAT_TOKENS_POST_EXPANSION_I_(_LEFT, _RIGHT) + +#define SOL_RAW_IS_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) != 0) +#define SOL_RAW_IS_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3) == 0) +#define SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL) ((3 OP_SYMBOL 3) > 3) +#define SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL) ((3 OP_SYMBOL 3 OP_SYMBOL 3) < 0) + +#define SOL_IS_ON(OP_SYMBOL) SOL_RAW_IS_ON(OP_SYMBOL ## _I_) +#define SOL_IS_OFF(OP_SYMBOL) SOL_RAW_IS_OFF(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_ON(OP_SYMBOL) SOL_RAW_IS_DEFAULT_ON(OP_SYMBOL ## _I_) +#define SOL_IS_DEFAULT_OFF(OP_SYMBOL) SOL_RAW_IS_DEFAULT_OFF(OP_SYMBOL ## _I_) + +#define SOL_ON | +#define SOL_OFF ^ +#define SOL_DEFAULT_ON + +#define SOL_DEFAULT_OFF - + +#if defined(SOL_BUILD_CXX_MODE) + #if (SOL_BUILD_CXX_MODE != 0) + #define SOL_BUILD_CXX_MODE_I_ SOL_ON + #else + #define SOL_BUILD_CXX_MODE_I_ SOL_OFF + #endif +#elif defined(__cplusplus) + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_CXX_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_BUILD_C_MODE) + #if (SOL_BUILD_C_MODE != 0) + #define SOL_BUILD_C_MODE_I_ SOL_ON + #else + #define SOL_BUILD_C_MODE_I_ SOL_OFF + #endif +#elif defined(__STDC__) + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_ON +#else + #define SOL_BUILD_C_MODE_I_ SOL_DEFAULT_OFF +#endif + +#if SOL_IS_ON(SOL_BUILD_C_MODE) + #include + #include + #include +#else + #include + #include + #include +#endif + +#if defined(SOL_COMPILER_VCXX) + #if defined(SOL_COMPILER_VCXX != 0) + #define SOL_COMPILER_VCXX_I_ SOL_ON + #else + #define SOL_COMPILER_VCXX_I_ SOL_OFF + #endif +#elif defined(_MSC_VER) + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_VCXX_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_GCC) + #if defined(SOL_COMPILER_GCC != 0) + #define SOL_COMPILER_GCC_I_ SOL_ON + #else + #define SOL_COMPILER_GCC_I_ SOL_OFF + #endif +#elif defined(__GNUC__) + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_GCC_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_CLANG) + #if defined(SOL_COMPILER_CLANG != 0) + #define SOL_COMPILER_CLANG_I_ SOL_ON + #else + #define SOL_COMPILER_CLANG_I_ SOL_OFF + #endif +#elif defined(__clang__) + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_CLANG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_EDG) + #if defined(SOL_COMPILER_EDG != 0) + #define SOL_COMPILER_EDG_I_ SOL_ON + #else + #define SOL_COMPILER_EDG_I_ SOL_OFF + #endif +#else + #define SOL_COMPILER_EDG_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_COMPILER_MINGW) + #if (SOL_COMPILER_MINGW != 0) + #define SOL_COMPILER_MINGW_I_ SOL_ON + #else + #define SOL_COMPILER_MINGW_I_ SOL_OFF + #endif +#elif defined(__MINGW32__) + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_ON +#else + #define SOL_COMPILER_MINGW_I_ SOL_DEFAULT_OFF +#endif + +#if SIZE_MAX <= 0xFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_ON + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_OFF +#elif SIZE_MAX <= 0xFFFFFFFFULL + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_ON + #define SOL_PLATFORM_X64_I_ SOL_OFF +#else + #define SOL_PLATFORM_X16_I_ SOL_OFF + #define SOL_PLATFORM_X86_I_ SOL_OFF + #define SOL_PLATFORM_X64_I_ SOL_ON +#endif + +#define SOL_PLATFORM_ARM32_I_ SOL_OFF +#define SOL_PLATFORM_ARM64_I_ SOL_OFF + +#if defined(SOL_PLATFORM_WINDOWS) + #if (SOL_PLATFORM_WINDOWS != 0) + #define SOL_PLATFORM_WINDOWS_I_ SOL_ON + #else + #define SOL_PLATFORM_WINDOWS_I_ SOL_OFF + #endif +#elif defined(_WIN32) + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_WINDOWS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_CYGWIN) + #if (SOL_PLATFORM_CYGWIN != 0) + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #else + #define SOL_PLATFORM_CYGWIN_I_ SOL_ON + #endif +#elif defined(__CYGWIN__) + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_CYGWIN_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_APPLE) + #if (SOL_PLATFORM_APPLE != 0) + #define SOL_PLATFORM_APPLE_I_ SOL_ON + #else + #define SOL_PLATFORM_APPLE_I_ SOL_OFF + #endif +#elif defined(__APPLE__) + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_ON +#else + #define SOL_PLATFORM_APPLE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_UNIX) + #if (SOL_PLATFORM_UNIX != 0) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_OFF + #endif +#elif defined(__unix__) + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_UNIXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_PLATFORM_LINUX) + #if (SOL_PLATFORM_LINUX != 0) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_ON + #else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_OFF + #endif +#elif defined(__LINUX__) + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAUKT_ON +#else + #define SOL_PLATFORM_LINUXLIKE_I_ SOL_DEFAULT_OFF +#endif + +#define SOL_PLATFORM_APPLE_IPHONE_I_ SOL_OFF +#define SOL_PLATFORM_BSDLIKE_I_ SOL_OFF + +#if defined(SOL_IN_DEBUG_DETECTED) + #if SOL_IN_DEBUG_DETECTED != 0 + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#elif !defined(NDEBUG) + #if SOL_IS_ON(SOL_COMPILER_VCXX) && defined(_DEBUG) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #elif (SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC)) && !defined(__OPTIMIZE__) + #define SOL_DEBUG_BUILD_I_ SOL_ON + #else + #define SOL_DEBUG_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_DEBUG_BUILD_I_ SOL_DEFAULT_OFF +#endif // We are in a debug mode of some sort + +#if defined(SOL_NO_EXCEPTIONS) + #if (SOL_NO_EXCEPTIONS != 0) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPUNWIND) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__EXCEPTIONS) + #define SOL_EXCEPTIONS_I_ SOL_OFF + #else + #define SOL_EXCEPTIONS_I_ SOL_ON + #endif +#else + #define SOL_EXCEPTIONS_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_RTTI) + #if (SOL_NO_RTTI != 0) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) + #if !defined(_CPPRTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) || SOL_IS_ON(SOL_COMPILER_GCC) + #if !defined(__GXX_RTTI) + #define SOL_RTTI_I_ SOL_OFF + #else + #define SOL_RTTI_I_ SOL_ON + #endif +#else + #define SOL_RTTI_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_NO_THREAD_LOCAL) + #if SOL_NO_THREAD_LOCAL != 0 + #define SOL_USE_THREAD_LOCAL_I_ SOL_OFF + #else + #define SOL_USE_THREAD_LOCAL_I_ SOL_ON + #endif +#else + #define SOL_USE_THREAD_LOCAL_I_ SOL_DEFAULT_ON +#endif // thread_local keyword is bjorked on some platforms + +#if defined(SOL_ALL_SAFETIES_ON) + #if SOL_ALL_SAFETIES_ON != 0 + #define SOL_ALL_SAFETIES_ON_I_ SOL_ON + #else + #define SOL_ALL_SAFETIES_ON_I_ SOL_OFF + #endif +#else + #define SOL_ALL_SAFETIES_ON_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_GETTER) + #if SOL_SAFE_GETTER != 0 + #define SOL_SAFE_GETTER_I_ SOL_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_GETTER_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_GETTER_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_USERTYPE) + #if SOL_SAFE_USERTYPE != 0 + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_USERTYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_USERTYPE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_REFERENCES) + #if SOL_SAFE_REFERENCES != 0 + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_REFERENCES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_REFERENCES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTIONS) + #if SOL_SAFE_FUNCTIONS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#elif defined (SOL_SAFE_FUNCTION_OBJECTS) + #if SOL_SAFE_FUNCTION_OBJECTS != 0 + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_OBJECTS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_FUNCTION_CALLS) + #if SOL_SAFE_FUNCTION_CALLS != 0 + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_FUNCTION_CALLS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_PROXIES) + #if SOL_SAFE_PROXIES != 0 + #define SOL_SAFE_PROXIES_I_ SOL_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_PROXIES_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_PROXIES_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_SAFE_NUMERICS) + #if SOL_SAFE_NUMERICS != 0 + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_NUMERICS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_NUMERICS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_ALL_INTEGER_VALUES_FIT) + #if (SOL_ALL_INTEGER_VALUES_FIT != 0) + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_ON + #else + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_OFF + #endif +#elif !SOL_IS_DEFAULT_OFF(SOL_SAFE_NUMERICS) && SOL_IS_OFF(SOL_SAFE_NUMERICS) + // if numerics is intentionally turned off, flip this on + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_ON +#else + // default to off + #define SOL_ALL_INTEGER_VALUES_FIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_SAFE_STACK_CHECK) + #if SOL_SAFE_STACK_CHECK != 0 + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_SAFE_STACK_CHECK_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_ON + #else + #define SOL_SAFE_STACK_CHECK_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_CHECK_NUMBER_PRECISION) + #if SOL_NO_CHECK_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#elif defined(SOL_NO_CHECKING_NUMBER_PRECISION) + #if SOL_NO_CHECKING_NUMBER_PRECISION != 0 + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_OFF + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_SAFE_NUMERICS) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_ON + #else + #define SOL_NUMBER_PRECISION_CHECKS_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_STRINGS_ARE_NUMBERS) + #if (SOL_STRINGS_ARE_NUMBERS != 0) + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_ON + #else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_OFF + #endif +#else + #define SOL_STRINGS_ARE_NUMBERS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_ENABLE_INTEROP) + #if SOL_ENABLE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#elif defined(SOL_USE_INTEROP) + #if SOL_USE_INTEROP != 0 + #define SOL_USE_INTEROP_I_ SOL_ON + #else + #define SOL_USE_INTEROP_I_ SOL_OFF + #endif +#else + #define SOL_USE_INTEROP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_NIL) + #if (SOL_NO_NIL != 0) + #define SOL_NIL_I_ SOL_OFF + #else + #define SOL_NIL_I_ SOL_ON + #endif +#elif defined(__MAC_OS_X_VERSION_MAX_ALLOWED) || defined(__OBJC__) || defined(nil) + #define SOL_NIL_I_ SOL_DEFAULT_OFF +#else + #define SOL_NIL_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USERTYPE_TYPE_BINDING_INFO) + #if (SOL_USERTYPE_TYPE_BINDING_INFO != 0) + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_ON + #else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_OFF + #endif +#else + #define SOL_USERTYPE_TYPE_BINDING_INFO_I_ SOL_DEFAULT_ON +#endif // We should generate a my_type.__type table with lots of class information for usertypes + +#if defined(SOL_AUTOMAGICAL_TYPES_BY_DEFAULT) + #if (SOL_AUTOMAGICAL_TYPES_BY_DEFAULT != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#elif defined(SOL_DEFAULT_AUTOMAGICAL_USERTYPES) + #if (SOL_DEFAULT_AUTOMAGICAL_USERTYPES != 0) + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_ON + #else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_AUTOMAGICAL_USERTYPES_I_ SOL_DEFAULT_ON +#endif // make is_automagical on/off by default + +#if defined(SOL_STD_VARIANT) + #if (SOL_STD_VARIANT != 0) + #define SOL_STD_VARIANT_I_ SOL_ON + #else + #define SOL_STD_VARIANT_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_COMPILER_CLANG) && SOL_IS_ON(SOL_PLATFORM_APPLE) + #if defined(__has_include) + #if __has_include() + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_OFF + #endif + #else + #define SOL_STD_VARIANT_I_ SOL_DEFAULT_ON + #endif +#endif // make is_automagical on/off by default + +#if defined(SOL_NOEXCEPT_FUNCTION_TYPE) + #if (SOL_NOEXCEPT_FUNCTION_TYPE != 0) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #endif +#else + #if defined(__cpp_noexcept_function_type) + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_ON + #elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(_MSVC_LANG) && (_MSVC_LANG < 201403L)) + // There is a bug in the VC++ compiler?? + // on /std:c++latest under x86 conditions (VS 15.5.2), + // compiler errors are tossed for noexcept markings being on function types + // that are identical in every other way to their non-noexcept marked types function types... + // VS 2019: There is absolutely a bug. + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_OFF + #else + #define SOL_USE_NOEXCEPT_FUNCTION_TYPE_I_ SOL_DEFAULT_ON + #endif +#endif // noexcept is part of a function's type + +#if defined(SOL_STACK_STRING_OPTIMIZATION_SIZE) && SOL_STACK_STRING_OPTIMIZATION_SIZE > 0 + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ SOL_STACK_STRING_OPTIMIZATION_SIZE +#else + #define SOL_OPTIMIZATION_STRING_CONVERSION_STACK_SIZE_I_ 1024 +#endif + +#if defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_ID_SIZE_I_ SOL_ID_SIZE +#else + #define SOL_ID_SIZE_I_ 512 +#endif + +#if defined(LUA_IDSIZE) && LUA_IDSIZE > 0 + #define SOL_FILE_ID_SIZE_I_ LUA_IDSIZE +#elif defined(SOL_ID_SIZE) && SOL_ID_SIZE > 0 + #define SOL_FILE_ID_SIZE_I_ SOL_FILE_ID_SIZE +#else + #define SOL_FILE_ID_SIZE_I_ 2048 +#endif + +#if defined(SOL_PRINT_ERRORS) + #if (SOL_PRINT_ERRORS != 0) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#else + #if SOL_IS_ON(SOL_ALL_SAFETIES_ON) + #define SOL_PRINT_ERRORS_I_ SOL_ON + #elif SOL_IS_ON(SOL_DEBUG_BUILD) + #define SOL_PRINT_ERRORS_I_ SOL_DEFAULT_ON + #else + #define SOL_PRINT_ERRORS_I_ SOL_OFF + #endif +#endif + +#if defined(SOL_DEFAULT_PASS_ON_ERROR) + #if (SOL_DEFAULT_PASS_ON_ERROR != 0) + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_ON + #else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_OFF + #endif +#else + #define SOL_DEFAULT_PASS_ON_ERROR_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUA) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUA) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUA_I_ SOL_ON + #else + #define SOL_USE_CXX_LUA_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUA_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USING_CXX_LUAJIT) + #if (SOL_USING_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#elif defined(SOL_USE_CXX_LUAJIT) + #if (SOL_USE_CXX_LUA != 0) + #define SOL_USE_CXX_LUAJIT_I_ SOL_ON + #else + #define SOL_USE_CXX_LUAJIT_I_ SOL_OFF + #endif +#else + #define SOL_USE_CXX_LUAJIT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_NO_LUA_HPP) + #if (SOL_NO_LUA_HPP != 0) + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #else + #define SOL_USE_LUA_HPP_I_ SOL_ON + #endif +#elif defined(SOL_USING_CXX_LUA) + #define SOL_USE_LUA_HPP_I_ SOL_OFF +#elif defined(__has_include) + #if __has_include() + #define SOL_USE_LUA_HPP_I_ SOL_ON + #else + #define SOL_USE_LUA_HPP_I_ SOL_OFF + #endif +#else + #define SOL_USE_LUA_HPP_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_CONTAINERS_START) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START +#elif defined(SOL_CONTAINERS_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINERS_START_INDEX +#elif defined(SOL_CONTAINER_START_INDEX) + #define SOL_CONTAINER_START_INDEX_I_ SOL_CONTAINER_START_INDEX +#else + #define SOL_CONTAINER_START_INDEX_I_ 1 +#endif + +#if defined (SOL_NO_MEMORY_ALIGNMENT) + #if (SOL_NO_MEMORY_ALIGNMENT != 0) + #define SOL_ALIGN_MEMORY_I_ SOL_OFF + #else + #define SOL_ALIGN_MEMORY_I_ SOL_ON + #endif +#else + #define SOL_ALIGN_MEMORY_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_USE_BOOST) + #if (SOL_USE_BOOST != 0) + #define SOL_USE_BOOST_I_ SOL_ON + #else + #define SOL_USE_BOOST_I_ SOL_OFF + #endif +#else + #define SOL_USE_BOOST_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_USE_UNSAFE_BASE_LOOKUP) + #if (SOL_USE_UNSAFE_BASE_LOOKUP != 0) + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_ON + #else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_OFF + #endif +#else + #define SOL_USE_UNSAFE_BASE_LOOKUP_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_INSIDE_UNREAL) + #if (SOL_INSIDE_UNREAL != 0) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_OFF + #endif +#else + #if defined(UE_BUILD_DEBUG) || defined(UE_BUILD_DEVELOPMENT) || defined(UE_BUILD_TEST) || defined(UE_BUILD_SHIPPING) || defined(UE_SERVER) + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_ON + #else + #define SOL_INSIDE_UNREAL_ENGINE_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if defined(SOL_NO_COMPAT) + #if (SOL_NO_COMPAT != 0) + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_OFF + #else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_ON + #endif +#else + #define SOL_USE_COMPATIBILITY_LAYER_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_GET_FUNCTION_POINTER_UNSAFE) + #if (SOL_GET_FUNCTION_POINTER_UNSAFE != 0) + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_ON + #else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_OFF + #endif +#else + #define SOL_GET_FUNCTION_POINTER_UNSAFE_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_FUNCTION_CALL_VALUE_SEMANTICS) + #if (SOL_FUNCTION_CALL_VALUE_SEMANTICS != 0) + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_ON + #else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_OFF + #endif +#else + #define SOL_FUNCTION_CALL_VALUE_SEMANTICS_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_MINGW_CCTYPE_IS_POISONED) + #if (SOL_MINGW_CCTYPE_IS_POISONED != 0) + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_ON + #else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_MINGW) && defined(__GNUC__) && (__GNUC__ < 6) + // MinGW is off its rocker in some places... + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_ON +#else + #define SOL_MINGW_CCTYPE_IS_POISONED_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_CHAR8_T) + #if (SOL_CHAR8_T != 0) + #define SOL_CHAR8_T_I_ SOL_ON + #else + #define SOL_CHAR8_T_I_ SOL_OFF + #endif +#else + #if defined(__cpp_char8_t) + #define SOL_CHAR8_T_I_ SOL_DEFAULT_ON + #else + #define SOL_CHAR8_T_I_ SOL_DEFAULT_OFF + #endif +#endif + +#if SOL_IS_ON(SOL_USE_BOOST) + #include + + #if BOOST_VERSION >= 107500 // Since Boost 1.75.0 boost::none is constexpr + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr + #else + #define SOL_BOOST_NONE_CONSTEXPR_I_ const + #endif // BOOST_VERSION +#else + // assume boost isn't using a garbage version + #define SOL_BOOST_NONE_CONSTEXPR_I_ constexpr +#endif + +#if defined(SOL2_CI) + #if (SOL2_CI != 0) + #define SOL2_CI_I_ SOL_ON + #else + #define SOL2_CI_I_ SOL_OFF + #endif +#else + #define SOL2_CI_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_C_ASSERT) + #define SOL_USER_C_ASSERT_I_ SOL_ON +#else + #define SOL_USER_C_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +#if defined(SOL_M_ASSERT) + #define SOL_USER_M_ASSERT_I_ SOL_ON +#else + #define SOL_USER_M_ASSERT_I_ SOL_DEFAULT_OFF +#endif + +// beginning of sol/prologue.hpp + +#if defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue was already included in translation unit and not properly ended with an epilogue." +#endif + +#define SOL_PROLOGUE_I_ 1 + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define _FWD(...) static_cast( __VA_ARGS__ ) + + #if SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define _MOVE(...) static_cast<__typeof( __VA_ARGS__ )&&>( __VA_ARGS__ ) + #else + #include + + #define _MOVE(...) static_cast<::std::remove_reference_t<( __VA_ARGS__ )>&&>( __VA_OPT__(,) ) + #endif +#endif + +// end of sol/prologue.hpp + +// beginning of sol/epilogue.hpp + +#if !defined(SOL_PROLOGUE_I_) + #error "[sol2] Library Prologue is missing from this translation unit." +#else + #undef SOL_PROLOGUE_I_ +#endif + +#if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #undef _FWD + #undef _MOVE +#endif + +// end of sol/epilogue.hpp + +// beginning of sol/detail/build_version.hpp + +#if defined(SOL_DLL) + #if (SOL_DLL != 0) + #define SOL_DLL_I_ SOL_ON + #else + #define SOL_DLL_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_COMPILER_VCXX) && (defined(DLL_) || defined(_DLL)) + #define SOL_DLL_I_ SOL_DEFAULT_ON +#else + #define SOL_DLL_I_ SOL_DEFAULT_OFF +#endif // DLL definition + +#if defined(SOL_HEADER_ONLY) + #if (SOL_HEADER_ONLY != 0) + #define SOL_HEADER_ONLY_I_ SOL_ON + #else + #define SOL_HEADER_ONLY_I_ SOL_OFF + #endif +#else + #define SOL_HEADER_ONLY_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_BUILD) + #if (SOL_BUILD != 0) + #define SOL_BUILD_I_ SOL_ON + #else + #define SOL_BUILD_I_ SOL_OFF + #endif +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_BUILD_I_ SOL_DEFAULT_OFF +#else + #define SOL_BUILD_I_ SOL_DEFAULT_ON +#endif + +#if defined(SOL_UNITY_BUILD) + #if (SOL_UNITY_BUILD != 0) + #define SOL_UNITY_BUILD_I_ SOL_ON + #else + #define SOL_UNITY_BUILD_I_ SOL_OFF + #endif +#else + #define SOL_UNITY_BUILD_I_ SOL_DEFAULT_OFF +#endif // Header only library + +#if defined(SOL_C_FUNCTION_LINKAGE) + #define SOL_C_FUNCTION_LINKAGE_I_ SOL_C_FUNCTION_LINKAGE +#else + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + // C++ + #define SOL_C_FUNCTION_LINKAGE_I_ extern "C" + #else + // normal + #define SOL_C_FUNCTION_LINKAGE_I_ + #endif // C++ or not +#endif // Linkage specification for C functions + +#if defined(SOL_API_LINKAGE) + #define SOL_API_LINKAGE_I_ SOL_API_LINKAGE +#else + #if SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) || SOL_IS_ON(SOL_PLATFORM_WINDOWS) || SOL_IS_ON(SOL_PLATFORM_CYGWIN) + // MSVC Compiler; or, Windows, or Cygwin platforms + #if SOL_IS_ON(SOL_BUILD) + // Building the library + #if SOL_IS_ON(SOL_COMPILER_GCC) + // Using GCC + #define SOL_API_LINKAGE_I_ __attribute__((dllexport)) + #else + // Using Clang, MSVC, etc... + #define SOL_API_LINKAGE_I_ __declspec(dllexport) + #endif + #else + #if SOL_IS_ON(SOL_COMPILER_GCC) + #define SOL_API_LINKAGE_I_ __attribute__((dllimport)) + #else + #define SOL_API_LINKAGE_I_ __declspec(dllimport) + #endif + #endif + #else + // extern if building normally on non-MSVC + #define SOL_API_LINKAGE_I_ extern + #endif + #elif SOL_IS_ON(SOL_UNITY_BUILD) + // Built-in library, like how stb typical works + #if SOL_IS_ON(SOL_HEADER_ONLY) + // Header only, so functions are defined "inline" + #define SOL_API_LINKAGE_I_ inline + #else + // Not header only, so seperately compiled files + #define SOL_API_LINKAGE_I_ extern + #endif + #else + // Normal static library + #if SOL_IS_ON(SOL_BUILD_CXX_MODE) + #define SOL_API_LINKAGE_I_ + #else + #define SOL_API_LINKAGE_I_ extern + #endif + #endif // DLL or not +#endif // Build definitions + +#if defined(SOL_PUBLIC_FUNC_DECL) + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_PUBLIC_FUNC_DECL +#else + #define SOL_PUBLIC_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DECL_) + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_INTERNAL_FUNC_DECL_ +#else + #define SOL_INTERNAL_FUNC_DECL_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_PUBLIC_FUNC_DEF) + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_PUBLIC_FUNC_DEF +#else + #define SOL_PUBLIC_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_INTERNAL_FUNC_DEF) + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_INTERNAL_FUNC_DEF +#else + #define SOL_INTERNAL_FUNC_DEF_I_ SOL_API_LINKAGE_I_ +#endif + +#if defined(SOL_FUNC_DECL) + #define SOL_FUNC_DECL_I_ SOL_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_FUNC_DEFN) + #define SOL_FUNC_DEFN_I_ SOL_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_FUNC_DEFN_I_ __declspec(dllexport) + #else + #define SOL_FUNC_DEFN_I_ __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_FUNC_DEFN_I_ __attribute__((visibility("default"))) + #else + #define SOL_FUNC_DEFN_I_ + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DECL) + #define SOL_HIDDEN_FUNC_DECL_I_ SOL_HIDDEN_FUNC_DECL +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DECL_I_ +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllexport) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern __declspec(dllimport) + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DECL_I_ extern __attribute__((visibility("default"))) + #else + #define SOL_HIDDEN_FUNC_DECL_I_ extern + #endif +#endif + +#if defined(SOL_HIDDEN_FUNC_DEFN) + #define SOL_HIDDEN_FUNC_DEFN_I_ SOL_HIDDEN_FUNC_DEFN +#elif SOL_IS_ON(SOL_HEADER_ONLY) + #define SOL_HIDDEN_FUNC_DEFN_I_ inline +#elif SOL_IS_ON(SOL_DLL) + #if SOL_IS_ON(SOL_COMPILER_VCXX) + #if SOL_IS_ON(SOL_BUILD) + #define SOL_HIDDEN_FUNC_DEFN_I_ + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif + #elif SOL_IS_ON(SOL_COMPILER_GCC) || SOL_IS_ON(SOL_COMPILER_CLANG) + #define SOL_HIDDEN_FUNC_DEFN_I_ __attribute__((visibility("hidden"))) + #else + #define SOL_HIDDEN_FUNC_DEFN_I_ + #endif +#endif + +// end of sol/detail/build_version.hpp + +// end of sol/version.hpp + +#if SOL_IS_ON(SOL_INSIDE_UNREAL_ENGINE) +#ifdef check +#pragma push_macro("check") +#undef check +#endif +#endif // Unreal Engine 4 Bullshit + +#if SOL_IS_ON(SOL_COMPILER_GCC) +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wshadow" +#pragma GCC diagnostic ignored "-Wconversion" +#if __GNUC__ > 6 +#pragma GCC diagnostic ignored "-Wnoexcept-type" +#endif +#elif SOL_IS_ON(SOL_COMPILER_CLANG) +#elif SOL_IS_ON(SOL_COMPILER_VCXX) +#pragma warning(push) +#pragma warning(disable : 4505) // unreferenced local function has been removed GEE THANKS +#endif // clang++ vs. g++ vs. VC++ + +// beginning of sol/forward.hpp + +#ifndef SOL_FORWARD_HPP +#define SOL_FORWARD_HPP + +#include +#include +#include + +#if SOL_IS_ON(SOL_USE_CXX_LUA) || SOL_IS_ON(SOL_USE_CXX_LUAJIT) +struct lua_State; +#else +extern "C" { +struct lua_State; +} +#endif // C++ Mangling for Lua vs. Not + +namespace sol { + + enum class type; + + class stateless_reference; + template + class basic_reference; + using reference = basic_reference; + using main_reference = basic_reference; + class stateless_stack_reference; + class stack_reference; + + template + class basic_bytecode; + + struct lua_value; + + struct proxy_base_tag; + template + struct proxy_base; + template + struct table_proxy; + + template + class basic_table_core; + template + using table_core = basic_table_core; + template + using main_table_core = basic_table_core; + template + using stack_table_core = basic_table_core; + template + using basic_table = basic_table_core; + using table = table_core; + using global_table = table_core; + using main_table = main_table_core; + using main_global_table = main_table_core; + using stack_table = stack_table_core; + using stack_global_table = stack_table_core; + + template + struct basic_lua_table; + using lua_table = basic_lua_table; + using stack_lua_table = basic_lua_table; + + template + class basic_usertype; + template + using usertype = basic_usertype; + template + using stack_usertype = basic_usertype; + + template + class basic_metatable; + using metatable = basic_metatable; + using stack_metatable = basic_metatable; + + template + struct basic_environment; + using environment = basic_environment; + using main_environment = basic_environment; + using stack_environment = basic_environment; + + template + class basic_function; + template + class basic_protected_function; + using unsafe_function = basic_function; + using safe_function = basic_protected_function; + using main_unsafe_function = basic_function; + using main_safe_function = basic_protected_function; + using stack_unsafe_function = basic_function; + using stack_safe_function = basic_protected_function; + using stack_aligned_unsafe_function = basic_function; + using stack_aligned_safe_function = basic_protected_function; + using protected_function = safe_function; + using main_protected_function = main_safe_function; + using stack_protected_function = stack_safe_function; + using stack_aligned_protected_function = stack_aligned_safe_function; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function = protected_function; + using main_function = main_protected_function; + using stack_function = stack_protected_function; + using stack_aligned_function = stack_aligned_safe_function; +#else + using function = unsafe_function; + using main_function = main_unsafe_function; + using stack_function = stack_unsafe_function; + using stack_aligned_function = stack_aligned_unsafe_function; +#endif + using stack_aligned_stack_handler_function = basic_protected_function; + + struct unsafe_function_result; + struct protected_function_result; + using safe_function_result = protected_function_result; +#if SOL_IS_ON(SOL_SAFE_FUNCTION_OBJECTS) + using function_result = safe_function_result; +#else + using function_result = unsafe_function_result; +#endif + + template + class basic_object_base; + template + class basic_object; + template + class basic_userdata; + template + class basic_lightuserdata; + template + class basic_coroutine; + template + class basic_packaged_coroutine; + template + class basic_thread; + + using object = basic_object; + using userdata = basic_userdata; + using lightuserdata = basic_lightuserdata; + using thread = basic_thread; + using coroutine = basic_coroutine; + using packaged_coroutine = basic_packaged_coroutine; + using main_object = basic_object; + using main_userdata = basic_userdata; + using main_lightuserdata = basic_lightuserdata; + using main_coroutine = basic_coroutine; + using stack_object = basic_object; + using stack_userdata = basic_userdata; + using stack_lightuserdata = basic_lightuserdata; + using stack_thread = basic_thread; + using stack_coroutine = basic_coroutine; + + struct stack_proxy_base; + struct stack_proxy; + struct variadic_args; + struct variadic_results; + struct stack_count; + struct this_state; + struct this_main_state; + struct this_environment; + + class state_view; + class state; + + template + struct as_table_t; + template + struct as_container_t; + template + struct nested; + template + struct light; + template + struct user; + template + struct as_args_t; + template + struct protect_t; + template + struct policy_wrapper; + + template + struct usertype_traits; + template + struct unique_usertype_traits; + + template + struct types { + typedef std::make_index_sequence indices; + static constexpr std::size_t size() { + return sizeof...(Args); + } + }; + + template + struct derive : std::false_type { + typedef types<> type; + }; + + template + struct base : std::false_type { + typedef types<> type; + }; + + template + struct weak_derive { + static bool value; + }; + + template + bool weak_derive::value = false; + + namespace stack { + struct record; + } + +#if SOL_IS_OFF(SOL_USE_BOOST) + template + class optional; + + template + class optional; +#endif + + using check_handler_type = int(lua_State*, int, type, type, const char*); + +} // namespace sol + +#define SOL_BASE_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct base : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() +#define SOL_DERIVED_CLASSES(T, ...) \ + namespace sol { \ + template <> \ + struct derive : std::true_type { \ + typedef ::sol::types<__VA_ARGS__> type; \ + }; \ + } \ + void a_sol3_detail_function_decl_please_no_collide() + +#endif // SOL_FORWARD_HPP +// end of sol/forward.hpp + +// beginning of sol/forward_detail.hpp + +#ifndef SOL_FORWARD_DETAIL_HPP +#define SOL_FORWARD_DETAIL_HPP + +// beginning of sol/traits.hpp + +// beginning of sol/tuple.hpp + +// beginning of sol/base_traits.hpp + +#include + +namespace sol { + namespace detail { + struct unchecked_t { }; + const unchecked_t unchecked = unchecked_t {}; + } // namespace detail + + namespace meta { + using sfinae_yes_t = std::true_type; + using sfinae_no_t = std::false_type; + + template + using void_t = void; + + template + using unqualified = std::remove_cv>; + + template + using unqualified_t = typename unqualified::type; + + namespace meta_detail { + template + struct unqualified_non_alias : unqualified { }; + + template